排序—快速排序

来源:互联网 发布:淘宝店铺如何删除宝贝 编辑:程序博客网 时间:2024/04/30 09:22

快速排序时实践中最快的一直排序,平均时间是0(NlogN),最坏的情况是O(N2)但是很容易将这种情况避免

空间复杂度:O(n*lgn),不稳定。

快速排序时基于分治模式处理的,
对一个典型子数组A[p...r]排序的分治过程为三个步骤:
1.分解:
A[p..r]被划分为俩个(可能空)的子数组A[p ..q-1]和A[q+1 ..r],使得
A[p ..q-1] <= A[q] <= A[q+1 ..r]
2.解决:通过递归调用快速排序,对子数组A[p ..q-1]和A[q+1 ..r]排序。
3.合并。


主要思想是选择一个pivot,将小于和大于他的数据分为两个集合,使用递归的处理方式得到最后的排序

选择枢纽元:

选择枢纽元将影响排序的时间复杂度,错误的方式是选择第一个元素作为枢纽元,但是如果是逆序的情况,这将变得十分糟糕,一种安全的做法是随机选择枢纽元,但是随机数的生成一般是比较昂贵的

我们选择一种三数中值分割法

将序列中的左端,右端,中间的数据进行比较,选择出来中间的数据作为枢纽元,同时完成他们的排序工作,左端是三者中的最小值,右端是三者中的最大值


问题:

在真正的过程中我们遇到一个问题,就是如果元素和枢纽元相等,是否对其进行交换

考虑都是相等数的情况,如果i,j都停止,交换没有意义,但是可以让i,j在中间交错,总时间为o(nlohN),产生两个几乎相等的子数组

如果i,j不停止,防止i,j越出数组的界限,最后枢纽元将交换到i最后到过的位置,产生两个非常不均衡的数组

因此我们选择在遇到相同元素的时候让i,j停下来,准备交换


小数组:对于很小的数组,快速排序不如插入排序好,因此我们将插入排序融入算法当中(具体实现)

小技巧:

由于之前的三数中值让左端,右端数据已经有序,所以i,j分别初始化为left+1,right-2,这样可以大大防止溢出

#include <iostream>using namespace :: std;void Swap(int & a,int &b){int temp;temp = a;a = b;b = temp;}int Median3(int *A, int left, int right){int Center = (left+right)/2;if (A[left] > A[Center]){Swap(A[left],A[Center]);}if (A[left] > A[right]){Swap(A[left],A[right]);}if (A[Center] > A[right]){Swap(A[Center],A[right]);}Swap(A[Center],A[right-1]);//A[Center] is pivot,hide itreturn A[right-1];//return pivot}void InsertionSort(int *A,int n){int j,p;int Tmp;for (p = 1; p<n; p++){Tmp = A[p];for (j = p; j > 0 && A[j-1] > Tmp; j--){A[j] = A[j-1];}A[j] = Tmp;}}#define Cutoff 3void Qsort(int *A,int left,int right){int i,j;int Pivot;if (left+Cutoff <= right){Pivot = Median3(A,left,right);i = left+1;j = right-2;for (;;){while (A[i]<Pivot){i++;}while (A[j]>Pivot){j--;}if (i < j){Swap(A[i],A[j]);}else{break;}}Swap(A[i],A[right-1]); //restore the pivotQsort(A,left,i-1);Qsort(A,i+1,right);}else{InsertionSort(A+left,right-left+1);}}void QuickSort(int * A,int n){Qsort(A,0,n-1);}void main(){int A[10] = {8,1,4,9,6,3,5,2,7,0};QuickSort(A,10);for (int i = 0; i < 10; i++){cout << A[i]<<" ";}}


后面是参考了一些网上的方法归纳总结的一些其余实现:

不进行递归的实现方法:

#include<iostream>#include<stack>using namespace std;int Partition(int array[],int lhs,int rhs){int x = array[rhs];int i = lhs - 1;for(int j=lhs;j<=rhs-1;j++){if(array[j] <= x){++i;swap(array[i],array[j]);}}    swap(array[i+1],array[rhs]);return i+1;}void QuickSort(int *arr,int left,int right){stack<int> st;if(left < right){int mid = Partition(arr,left,right);if(left < mid-1){st.push(left);st.push(mid-1);}if(mid+1 < right){st.push(mid+1);st.push(right);}while(!st.empty()){int q = st.top();st.pop();int p = st.top();st.pop();mid = Partition(arr,p,q);if(p < mid-1){st.push(p);st.push(mid-1);}if(mid+1 < q){st.push(mid+1);st.push(q);}       }}elsereturn;}int main(){int a[10] ={3,7,6,4,0,2,9,8,1,5};  for(int i=0;i<10;i++)cout<<a[i]<<" ";cout<<endl; cout<<"快速排序:";QuickSort(a,0,9);for(int i=0;i<10;i++)cout<<a[i]<<" ";cout<<endl;system("PAUSE");return 0;}

#include <iostream>  using namespace std;  //算法导论上的实现 ,quicksort_1   int Partition(int array[],int lhs,int rhs)  {  int x = array[rhs];  int i = lhs - 1;  for(int j=lhs;j<=rhs-1;j++)  {  if(array[j] <= x)  {  ++i;  std::swap(array[i],array[j]);  }  }  std::swap(array[i+1],array[rhs]);  return i+1;  }  void quickSort_1(int array[],int lhs,int rhs)  {  while(lhs < rhs)  {  int q = Partition(array,lhs,rhs);   quickSort_1(array,lhs,q-1);  lhs = q + 1;      //      quickSort(array,q+1,rhs);   //消除尾递归,利用迭代控制   }  }int main(){int a[10] ={3,7,6,4,0,2,9,8,1,5};  for(int i=0;i<10;i++)cout<<a[i]<<" ";cout<<endl; cout<<"快速排序:";quickSort_1(a,0,9);for(int i=0;i<10;i++)cout<<a[i]<<" ";cout<<endl;system("PAUSE");return 0;}



0 0