【交换排序】快速排序

来源:互联网 发布:淘宝信誉刷钻平台 编辑:程序博客网 时间:2024/05/01 12:06
快速排序(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 0
原创粉丝点击