【交换排序】快速排序

快速排序(Quick Sort)

   快速排序是由冒泡排序改进而得的。在冒泡排序过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。如果能通过两个(不相邻)记录的依次交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中的一次交换可能消除多个逆序。

[算法思想]

   在待排序的n个记录中任取一个记录(通常取第一个记录)作为枢轴(或支点),设其关键字为pivotkey。经过一趟排序后,把所有关键字小于pivotkey的记录交换到前面,把所有关键字大于pivotkey的记录交换到后面,结果将待排序记录分成两个子表,最后将枢轴放置在分界处的位置。然后,分别对左、右子表重复上述过程,直至每一子表只有一个子记录时,排序完成。又是分治的思想,分解,解决,合并

   其中,一趟快速排序的具体做法如下。

   1)附设两个指针low和high,初始时分别指向表的下界和上界,设枢轴记录的关键字为pivotkey(第一趟时,low=1;high=L.length;)

   2)从表的最右侧位置,依次向左搜索找到第一个关键字小于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若high所指的关键字大于等于pivotkey,则向左移动指针high,(执行操作--high);否则将high所指记录与枢轴记录交换。

   3)然后再从表的最左侧位置,依次向右搜索找到第一个关键字大于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若low所指的关键字小于等于pivotkey,则向右移动指针low(执行操作++low);否则将low所指记录与枢轴记录交换。

   4)重复步骤(2)和步骤(3),直到low与high相等为止。此时low或high的位置即为枢轴在此趟排序中的最终位置,原表被分成两个子表。

  在上述过程中,记录的交换都是与枢轴之间发生,每次交换都要移动3次记录,可以先将枢轴记录暂存在r[0]的位置上,排序过程中只移动要与枢轴交换的记录,即只做r[low]或r[high]的单向移动,直至一趟排序记录结束后再将枢轴记录移至正确的位置上。

例 已知待排序记录的关键字序列为{49,38,65,97,76,13,27,49},请给出快速排序法进行排序的过程。

 每一趟快速排序过程如图(a)所示,整个快速排序的过程如图(b)所示。

 [算法描述]
 
int Partition(int L[],int low ,int high)
 {
	/*对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置*/
	L[0]=L[low];      /*用子表的第一个记录做枢轴记录*/
	int pivotkey=L[low];  /*枢轴记录关键字保存在pivotkey中*/
	while(low < high)    /*从表的两端交替地向中间扫描*/
	{
	   while(low<high && L[high]>=pivotkey) --high;
	   L[low]=L[high];
	   while(low<high && L[low]<=pivotkey) ++low;
	   L[high]=L[low];
	}
	L[low]=L[0];        /*枢轴记录到位*/
	return low;
 }
 void Qsort(int L[],int low,int high)
 {
	/*对顺序表L中的子序列L[low..high]做快速排序*/
	if(low<high)       /*长度大于1*/
	{
	   int pivotloc=Partition(L,low,high);    /*将L[low..high]一分为二,pivotloc是枢轴位置*/
	   Qsort(L,low,pivotloc-1);               /*对左子表递归排序*/
	   Qsort(L,pivotloc+1,high);              /*对右子表递归排序*/
	   
	}
 }
 void QuickSort(int L,int n)
 {
	Qsort(L,1,n);
 }

 [算法分析]

 1)时间复杂度

 最好O(nlog2n);最坏O(n^2);平均O(nlog2n);

 2)空间复杂度

 快速排序是递归的,执行时需要一个栈来存放相应的数据。最大递归调用次数与递归树的深度一致,所以最好情况下的空间复杂度为O(log2n)最坏情况下为O(n).

 [完整代码]
  
#include<iostream>
  using namespace std;
  int Partition(int L[],int low ,int high)
  {
	/*对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置*/
	L[0]=L[low];      /*用子表的第一个记录做枢轴记录*/
	int pivotkey=L[low];  /*枢轴记录关键字保存在pivotkey中*/
	while(low < high)    /*从表的两端交替地向中间扫描*/
	{
	   while(low<high && L[high]>=pivotkey) --high;
	   L[low]=L[high];
	   while(low<high && L[low]<=pivotkey) ++low;
	   L[high]=L[low];
	}
	L[low]=L[0];        /*枢轴记录到位*/
	return low;
  }
  void Qsort(int L[],int low,int high)
  {
	/*对顺序表L中的子序列L[low..high]做快速排序*/
	if(low<high)       /*长度大于1*/
	{
	   int pivotloc=Partition(L,low,high);    /*将L[low..high]一分为二,pivotloc是枢轴位置*/
	   Qsort(L,low,pivotloc-1);               /*对左子表递归排序*/
	   Qsort(L,pivotloc+1,high);              /*对右子表递归排序*/
	   
	}
  }
  void QuickSort(int L[],int n)
  {
	Qsort(L,1,n);
  }
  int main()
  {
	 int ans[9]={0,49,38,65,97,76,13,27,49};
	 QuickSort(ans,8);
	 for(int i=1;i<=8;i++)
		 cout<<ans[i]<<" ";
	 return 0;
  }

[运行结果]

  
  附:<啊哈!算法>里快排的实现
  
#include<stdio.h>
  int a[101],n;
  void quicksort(int left,int right)
  {
	int i,j,t,temp;
	if(left>right)
	{
		return ;
	}
	temp=a[left]; /*temp中存的就是基准数*/
	i=left;
	j=right;
	while(i!=j)
	{
		/*顺序很重要 要先从右往左*/
		while(a[j] >= temp && i<j)
			j--;
		while(a[i] <= temp && i<j)
			i++;
		if(i<j)          /*交换两个数的位置*/
		{
			t=a[i];
			a[i]=a[j];
			a[j]=t;
		}
	}
	/*最终将基准数归位,交换*/
	a[left]=a[i];
	a[i]=temp;
	
	quicksort(left,i-1);          /*继续处理左边的,这是一个递归的过程*/
	quicksort(i+1,right);         /*继续处理右边的,这是一个递归的过程*/
	return ;
   }
   int main()
   {
	  int i,j;
	  scanf_s("%d",&n);
	  for(i=1;i<=n;i++)
	 {
		scanf_s("%d",&a[i]);
	 }
	quicksort(1,n);

	/*输出排序后的结果*/
	for(i=1;i<=n;i++)
	{
		printf("%d ",a[i]);
	}
	getchar();
	return 0;
   }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值