交换排序之——快速排序(c/c++)

快速排序的思想是,以某个元素为基准(一般取第一个元素),将其余数分为两部分,一部分比基准的值小,另一部分比基准的值大,然后在这两部分中通过与新的基准值作比较,分为四部分,再分为八部分,以次类推直到排序结束。这其中蕴含了递归与分治的思想。例如:

对数列 49 38 65 97 13 27 55 04进行快速排序,取第一个数49为基准将其余数分为两部分

04 38 27 13 49 97 55 65   再以49为中心分为两部分,左边以04为基准,右边以97为基准进行划分

04 38 27 13 49 65 55 97   类似的,38 27 13 以38为基准,65 55 以65为基准进行划分

04 13 27 38 49 55 65 97   13 27 以13为基准进行划分,55一个数不满足函数执行条件,不用划分

04 13 27 38 49 55 65 97    只剩27一个数了,不做任何改变,算法执行结束。最终结果为

04 13 27 38 49 55 65 97

快速排序每一次以某个基准划分时,都会将该基准数放置于它应该所在的最终位置上。


快速排序时间复杂度为o(nlogn),空间复杂度为o(logn)(程序执行中栈的深度)。当数列基本处于正序或逆序时,快速排序的时间复杂度和空间复杂度会增大,分别会达到o(n^{2})和o(n)。


快速排序我本人之前经常写成如下这样:

  int partion(int* arr, int low, int high)
  {
	  int temp = arr[low];//保存基准值
	  int i = low, j = high;
	  while (i < j)
	  {
		  while (i<j&&arr[j]>temp)//先从后面开始比较
			  j--;
		  if (i < j)
			  arr[i] = arr[j];
		  while (i<j&&arr[i] < temp)
			  i++;
		  if (i < j)
			  arr[j] = arr[i];
	  }
	  arr[i] = temp;//写成arr[j]=temp也可以,i是等于j的
	  return i;
  }

写这篇文章时,我发现这种写法的缺点在于有可能会导致程序会陷入无限循环,例如对于 49 49 50进行排序,它会不停将49与49进行交换,直至天荒地老。

所以更正如下:

arr[i++] = arr[j];
		
arr[j--] = arr[i];

快速排序是一种不稳定的排序方法。

当采用arr[j]>temp,arr[i]<temp时,对于49 49 50 来讲,排序结果为49 49 50 ,不稳定;

采用arr[j]>=temp,arr[i]<=temp时,对于 49 38 49 04来讲,排序结果为 04 38 49 49,仍然是不稳定的。


快速排序完整代码如下:

  #include<iostream>
  #define N 20
  void qSort(int* arr, int low,int high);
  int partion(int* arr, int low, int high);//返回基准值所处的位置,方便递归调用
  int main()
  {
	  int a[N] = { 3, 2, 4, 6, 7, 5, 18, 9, 0, 1,
		  16, 8, 20, 33, 28, 64, 19, 31, 30, 25 };
	  for (int i = 0; i < N; i++)
	  {
		  std::cout << a[i] << "  ";
	  }
	  std::cout << '\n'; 
	  qSort(a, 0,N-1);
	  for (int i = 0; i < N; i++)
	  {
		  std::cout << a[i] << "  ";
	  }
	  std::cout << '\n';
	  return 0;
  }

  void qSort(int* arr, int low,int high)
  {
	  if (low<high)
	  {
		  int a = partion(arr, low, high);
		  qSort(arr, low, a - 1);//递归调用
		  qSort(arr, a + 1, high);//递归调用
	  }
  }
  int partion(int* arr, int low, int high)
  {
	  int temp = arr[low];//保存基准值
	  while (low < high)
	  {
		  while (low < high&&arr[high]>temp)//先从后面开始比较
			  high--;
		  if (low < high)//最好不要省略,足以保证在while执行完之后i定是等于j的
			  arr[low++] = arr[high];
		  while (low<high&&arr[low] < temp)
			  low++;
		  if (low < high)
			  arr[high--] = arr[low];
	  }
	  arr[low] = temp;//写成arr[high]=temp也可以,low是等于high的
	  return low;
  }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值