排序算法——冒泡&选择&快排&归并

冒泡排序
思想:
(1)将相邻的两个数 Ai 和 A(i+1) 进行比较,如果 A(i+1) 较大,则交换 Ai 和 A(i+1) ;
(2)如果 Ai 较大,则不交换;
(3)每次排序后都将未排序好的最大的数冒到指定位置。

时间复杂度:O(N^2)

每次排序结果:
冒泡排序
代码:

void bubble_sort(int* a, int n)
{
      int flag = 0;
      for (int i = 0; i < n-1; i++)
      {
            for (int j = 0; j < n-i-1; j++)
            {
                  if (a[j] > a[j + 1])
                  {
                        swap(a[j], a[j + 1]);
                        flag = 1;
                  }
            }
            if (flag == 0)
                  break;
      }
}

选择排序
思想:
(1)对数组设置begin和end,也就是第一个元素和最后一个元素的下标;
(2)遍历一遍数组找最大值的下标max和最小值下标min;
(3)将找到的最大值max和end的值进行交换,最小值min和begin的值进行交换;
(4)此时最大值和最小值已经位于最终的位置上;
(5)之后将begin++,end–,调整数组区间,继续进行上述的过程。

时间复杂度:O(N^2)

每次排序结果:
代码:

void select_sort(int* a, int n)
{
      //从两端缩小范围
      int begin = 0;
      int end = n - 1;
      while (begin < end)
      {
            int max = begin;
            int min = end;
            for (int i = begin; i <= end; i++)
            {
                  if (a[max] < a[i])
                        max = i;
                  if (a[min] > a[i])
                        min = i;
            }
            swap(a[max], a[end]);
            //可能在a[max]和a[end]交换之后,找不到a[min]的值
            if (min == end)
            {
                  min = max;
            }
            swap(a[min], a[begin]);
            ++begin;
            --end;
      }
}

快速排序
思想:以数组最右端的数为key值为例
(1)设置begin为A[0],end为A[n],key = A[n];
(2)从begin开始向后找比key大的值,从end开始向前查找比key小的值;
(3)找到后,将A[begin]和A[end]的值交换,之后begin++,end–;
(4)直至begin和end相遇,将 key 值与 A[end] 交换,此次快排结束,一次快排之后可以保证key前面的数一定以key小,key后面的数一定比key大;
(5)将整个数组分为两部分:key值之前,key值之后,再次进行上述操作…;
(6)直至begin和end的区间内之后一个数,表明排序结束。

时间复杂度:最好O(N*logN) 平均:O(N^2)

每次排序结果:
快速排序
代码:

int _quick_sort (int* a, size_t left, size_t right)
{
      size_t begin = left;
      size_t end = right;
      int key = a[right];
      while (begin < end)
      {
            while (begin < end && a[begin] <= key)
                  ++begin;
            while (begin < end && a[end] >= key)
                  --end;
            swap(a[begin], a[end]);
      }
      swap(a[begin], a[right]);
      return begin;
}
void quick_sort(int* a, int left,int right)
{
      assert(a);
      if (left >= right)
            return;
      else
      {
            int div =_quick_sort (a, left, right);
            quick_sort(a, left, div - 1);
            quick_sort(a, div + 1, right);
      }
}

归并排序
思想:
(1)对于已经排序完成的两个子数组,按顺序进行合并;
(2)合并时首先开辟一个与数组大小相同的新数组tmp,选择两个数组中较小的数值放在数组tmp中;
(3)遍历两个子数组,依次放置在tmp中,此时tmp中为已经排序完成的数组;
(4)将tmp中的内容,替换原数组;

每次排序结果:
归并排序
代码:

void _mergesort(int* a, int left, int right, int* tmp)
{
      if (left >= right)
            return;
      int mid = left + ((right - left) >> 1);
      _mergesort(a, left, mid, tmp);
      _mergesort(a, mid + 1, right, tmp);
      int begin1 = left;
      int end1 = mid;
      int begin2 = mid + 1;
      int end2 = right;

      int i = 0;
      while (begin1 <= end1 && begin2 <= end2)
      {
            if (a[begin1] <= a[begin2])
            {
                  tmp[i] = a[begin1];
                  begin1++;
            }
            else
            {
                  tmp[i] = a[begin2];
                  begin2++;
            }
            i++;
      }
      if (begin1 <= end1)
      {
            tmp[i] = a[begin1];
            begin1++;
            i++;
      }
      else if (begin2 <= end2)
      {
            tmp[i] = a[begin2];
            begin2++;
            i++;
      }
      for (int j = 0; j < i; j++)
      {
            a[j+left] = tmp[j];
      }
}
void merge_sort(int* a, int left,int right)
{
      assert(a);
      if (left >= right)
            return;
      int* tmp = new int[right - left + 1];
      _mergesort(a, left, right, tmp);
}

猜你喜欢

转载自blog.csdn.net/weixin_39294633/article/details/81709669