排序--5.快排

来源:互联网 发布:音乐推荐算法 lr gbdt 编辑:程序博客网 时间:2024/05/15 00:36

1.原地排序,不稳定的,时间复杂度O(nlogn),尽管最坏情况下是n^2,即每次选的partition都是边界值,但这种情况几乎不会发生。

   思想:数据x前边的都比它小,后边的都比它大

不稳定情况的例子,比如有两个3,选择的轴心是前面的3,那么在对比时后面的3会跑到前面。

2.快排中调用的partition函数 可以有多种选择形式,意在选出一个较好的轴心x。此处列出选用尾节点a[right]作为轴心,如果随机选取只要将其与a[right]交换位置,

再调用该partition函数即可。

hoare-partition的思想是:j从后往前找比x小的,i是从前往后找比x大的,如果找到了但i<j就交换二者继续找,最后j的位置就是轴心,能够很好地代表中间性

public static void quickSort(int[] array,int left,int right){//递归,此处right=lenght-1;left=0int q;if(left<right){q=partition(array,left,right);quickSort(array,left,q-1);quickSort(array, q+1, right);}}public static int partition(int[] array,int left,int right){//筛选基准//基于随机位置的partition,先选取随机位置index->a[index]和a[right]交换位置,然后在调用此partitionint x=array[right];//以末尾元素为基准(或以首元素为基准)int i=left-1;for(int j=left;j<right;j++){if(array[j]<=x){i++;//注意 先i++再交换a[j]和a[i]int temp=array[j];array[j]=array[i];array[i]=temp;}}int t=array[i+1];//i+1的位置是尾元素的位置,交换二者array[i+1]=array[right];array[right]=t;return i+1;//x的位置}public static int hoarePartition(int[] array,int left,int right){//原始的划分方法//参数right=len-1;int x=array[left];//x为首个元素int i=left;int j=right;while(true){for(;i<right&&array[j]>=x;j--);//j从后往前找,找到比x小的位置for(;j>left&&array[i]<=x;i++);//i从前往后找,找到比x大的位置if(i<j){//i处是比x大的,j处是比x小的,二者交换位置,继续重复两个forint temp=array[i];array[i]=array[j];array[j]=temp;}else{//找到的位置i=j 就说明该位置是合适的划分位置//array[j]=x;//这句是当采用非递归快排时用到的,如果采用递归快排则不需要这句******return j;}}}


3.非递归快排:借助来完成,调用hoare-partition(返回轴心j之前,a[j]=x 相当于排序部分,而在快排函数里入栈出栈的是下标)

记住入栈出栈的顺序,入栈时:先左后右,则出栈时先右后左

public static int hoarePartition(int[] array,int left,int right){//原始的划分方法//参数right=len-1;int x=array[left];//x为首个元素int i=left;int j=right;while(true){for(;i<right&&array[j]>=x;j--);//j从后往前找,找到比x小的位置for(;j>left&&array[i]<=x;i++);//i从前往后找,找到比x大的位置if(i<j){//i处是比x大的,j处是比x小的,二者交换位置,继续重复两个forint temp=array[i];array[i]=array[j];array[j]=temp;}else{//找到的位置i=j 就说明该位置是合适的划分位置array[j]=x;//这句是当采用非递归快排时用到的,如果采用递归快排则不需要这句******return j;}}}public static void quickSort2(int[] array){//非递归快排if(array==null||array.length==1) return;Stack<Integer> s=new Stack();//存放开始于结束索引s.push(0);//注意向将左指针入栈,下面出栈时先出的是rights.push(array.length-1);while(!s.isEmpty()){int right=s.pop();//上面入栈是先左指针后右指针,则出栈先右指针后左指针int left=s.pop();if(right<=left) continue;//如果最大索引《=左边索引说明结束int i=partition(array, left, right);//选出轴心if(left<i-1){s.push(left);//先左后右s.push(i-1);}if(i+1<right){s.push(i+1);//先左后右s.push(right);}}}


0 0
原创粉丝点击