数据结构:常见的排序算法(六):快速排序(C++实现)

数据结构:常见的排序算法(六):快速排序

1.基本思想:

选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一轮扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分,直到各区间只有一个数。

2.实例

示例:数组a[15]={3,44,38,5,47,15,36,26,2,46,4,19,50,48}通过快速排序进行排序

img

img

图片来源:https://www.cnblogs.com/zwtgyh/p/10631760.html

实例代码:

//辅助函数:交换值
void exchange(int * a, int* b) {
  int temp = *a;
  *a = *b;
  *b = temp;
}

//打印数组函数
void print_arr(int *a, int size) 
{
  cout << "打印数组:";
  for (int i = 0; i<size; i++)  //打印数组 
  {
    cout << a[i] << " ";
  }
  cout << endl << endl;
}
/*序列划分函数*/
int partition(int a[], int p, int r) {
  int key = a[r];//取最后一个
  int i = p - 1;
  for (int j = p; j < r; j++)
  { 
    if (a[j] <= key)
    {     
      i++;
      //i一直代表小于key元素的最后一个索引,当发现有比key小的a[j]时候,i+1 后交换     
      exchange(&a[i], &a[j]);
    }   
  } 
  exchange(&a[i + 1], &a[r]);//将key切换到中间来,左边是小于key的,右边是大于key的值。
  return i + 1;
}
  
void quickSort(int a[], int p, int r) {
  int position = 0;
  if (p<r)
  {
    position = partition(a,p,r);//返回划分元素的最终位置
    quickSort(a,p,position-1);//划分左边递归
    quickSort(a, position + 1,r);//划分右边递归
  } 
}
  //主函数
void main() {
  int a[15]={3,44,38,5,47,15,36,26,2,46,4,19,50,48};
  cout << "输入数组 a[15]={3,44,38,5,47,15,36,26,2,46,4,19,50,48} " << endl; 
  quickSort(a, 0, 14);
  print_arr(a, 15);
  
}

3.总结:

  • 最好情况:是每轮划分都将待排序列正好分为两部分,那么每部分需要的时间为上一轮的1/2。如果排序n个元素的序列,其递归树深度为[logn]+1即仅需递归logn次,需要总时间为T(n)的话,第一次需要扫描整个序列,做n次比较,然后将序列一分为二,这两部分各自还需要T(n/2)的时间,依次划分下去:T(n) = 2T(n/2)+n T(n) = 2(2*(T(n/4)+n/2)+n = 4T(n/4)+2n 等等,且T(1) = 0,所以T(n) = nT(1) + n*logn = O(nlogn)
  • 最坏情况:当待排序列为有序序列(正序或倒序),每次划分后得到的情况是一侧有1个元素,另一侧是其余元素,则最终要进行n-1轮循环,且第i次循环要进行n-i次比较,总比较次数为n-1 + n-2 + … + 1 = n(n-1)/2,即时间复杂度为O(n^2)
  • 快速排序为原址排序,不需要额外的内存空间.
  • 快速排序不是稳定排序, 在交换过程中会破坏稳定性。

猜你喜欢

转载自blog.csdn.net/qq_43801020/article/details/108137304