冒泡排序

 

算法思路

  • 升序排列:

    • 从左到右(或右到左)比较相邻的元素,如果当前元素比下一个元素大(或者小),就交换他们两个。
    • 对下一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,本轮排序完成后得到无序部分中的最大元
      素,此时这个最大元素和之前的已经排序的部分,组成新的有序部分
    • 针对所有的无序元素重复以上的步骤,直到某一轮没有发生元素交换则说明排序完成
  • 降序排列:

    • 从左到右(或右到左)比较相邻的元素,如果当前元素比下一个元素小(或者大),就交换他们两个。
    • 对下一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,本轮排序完成后得到无序部分中的最大元
      素,此时这个最大元素和之前的已经排序的部分,组成新的有序部分
    • 针对所有的无序元素重复以上的步骤,直到某一轮没有发生元素交换则说明排序完成

    例:使冒泡法升序排列8,1,6,3,2,4
    从左到右进行排序:
    第一轮:
    20190811213852.png
    第二轮:
    20190811214049.png
    第三轮:
    20190811214304.png
    第四轮:
    20190811214344.png
    本轮中没有发生元素交换,就表示剩下的元素都是有序的,所以所有元素已经都是有序的了。

代码实现

bool BubbleSort(int * pUnSortAry, int nArySize)
{
  if (pUnSortAry == nullptr || nArySize <= 0)
  {
    return false;
  }

  bool bFlag = false;
  for (int iIndex = 0; iIndex < nArySize; iIndex++)
  {
    for (int jIndex = 0; jIndex < nArySize - iIndex -1; jIndex++)
    {
      if (pUnSortAry[jIndex] > pUnSortAry[jIndex + 1])
      {
        int nTemp = pUnSortAry[jIndex];
        pUnSortAry[jIndex] = pUnSortAry[jIndex + 1];
        pUnSortAry[jIndex + 1] = nTemp;
        bFlag = true;
      }
    }

    if (!bFlag)
    {
      break; //如果内存for循环中一次交换也没有发生,则说明所有元素已经有序
    }
  }
  return true;
}

测试代码:

void PrintData(int*pAry, int nSize)
{
  for (int jIndex = 0; jIndex < nSize; jIndex++)
  {
    printf("%d ", pAry[jIndex]);
  }
  printf("\r\n");
}

int main()
{
  srand(time(NULL));

  int nArry[20] = { 0 };

  for (int jIndex = 0; jIndex < 10; jIndex++)
  {
    for (int iIndex = 0; iIndex < sizeof(nArry) / sizeof(nArry[0]); iIndex++)
    {
      nArry[iIndex] = rand() % 150;
    }
    printf("排序前:");
    PrintData(nArry, sizeof(nArry) / sizeof(nArry[0]));
    BubbleSort(nArry, sizeof(nArry) / sizeof(nArry[0]));
    printf("排序后:");
    PrintData(nArry, sizeof(nArry) / sizeof(nArry[0]));
  }
}

测试结果:
20190811214924.png

时间复杂度分析

核心部分代码如下,假设待排序元素有n个

//执n次
for (int iIndex = 0; iIndex < nArySize; iIndex++)  
{   
    //执行1+2+.....+n次
    for (int jIndex = 0; jIndex < nArySize - iIndex -1; jIndex++)
    {
      //执行1+2+.....+(n-1)次
      if (pUnSortAry[jIndex] > pUnSortAry[jIndex + 1])
      {
          //执行(1/n)*(1+2+3...+n-1)
          int nTemp = pUnSortAry[jIndex];
          pUnSortAry[jIndex] = pUnSortAry[jIndex + 1];
          pUnSortAry[jIndex + 1] = nTemp;
          bFlag = true;
      }
    }

    //执行n次
    if (!bFlag)
    {
      //执行一次
        break; //如果内存for循环中一次交换也没有发生,则说明所有元素已经有序
    }
}

平均时间复杂度为:T(n) =n+n+(1+2....+n) + (1+2....+(n-1)) + (1/n)(1+2+3...+n-1))
= 2n + 2
(1+2...+n) - n + (1/n)*(1+2+3...+n-1 + n) -1
= n + n(1+n) + (1/2n)*n(1+n) -1
= n^2 + (5n)/2 -1/2
= O(n^2)

当元素已经是有序的情况下时间复杂度为T(n)=O(n)

稳定性

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元
素之间。所以,如果两个元素相等,则不会进行交换如果两个相等的元素没有相邻,那么即使通过前面的两两
交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排
序算法。

 

posted @ 2019-08-12 08:53  CodeMaker+  阅读(529)  评论(0编辑  收藏  举报