排序—快速排序
来源:互联网 发布:淘宝店铺如何删除宝贝 编辑:程序博客网 时间: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;}
- 排序—快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 交换排序—快速排序
- 排序算法—快速排序
- 排序算法—快速排序
- 内部排序—快速排序
- 排序方式—/冒泡排序/快速排序
- 排序3——堆排序,归并排序,快速排序
- 快速排序—java
- Dblink 实现数据库表同步
- jni常用函数
- linux centos7.0装搜狗拼音 sougou
- Android学习笔记 初识
- 蚌埠婚纱照
- 排序—快速排序
- WIN32编程--用Windows API实现Windows NT服务的程序框架
- excel 导入 sql数据库 错误如下:返回列状态:文本被截断,或者一个或多个字符在目标代码页中没有匹配项。
- 面试题8-旋转数组的最小数字
- iPhone 6大陆预订量突破2000万部
- cocos2dx auto culling 和 auto batching
- ovs安装教程
- 应用程序已被安全设置阻止 Java(来自百度收藏)
- 世界上的程序语言已这么丰富,为什么还不够?