排序法里比较出名的,具体的算法看下图:
这篇博客说的通俗易懂:http://blog.csdn.net/morewindows/article/details/6684558
这是快速排序的基础,用代码实现如下:
void DiviedSort(int* arr_p,int start,int end) { int left,right,i=0; int pivot,result; bool flag; flag = TRUE; pivot = arr_p[start]; right = end; left = start; #if DEBUG printf("pivot:%d\r\n",pivot); printf("L: "); for(i=0;i<end+1;i++){ if(i==0) printf("_ "); else printf("%d ",arr_p[i]); } printf("\r\n"); #endif while(left<right && flag){ while(arr_p[right]>=pivot){ right--; if(right<=left){ //右边没有找到小于pivot的数 退出总循环 arr_p[left] = pivot; //将pivot保存到左边的坑里 flag = FALSE; break; } } if(flag){ //找到小于pivot的数移动到left arr_p[left] = arr_p[right]; arr_p[right] = 1000; left++; if(left>=right){ flag = FALSE; arr_p[right] = pivot;//当left右移等于right说明正好结束; } }else{ #if DEBUG printf("Lf: "); for(i=0;i<end+1;i++){ if(arr_p[i]==1000) printf("_ "); else printf("%d ",arr_p[i]); } printf("\r\n"); #endif break; } #if DEBUG printf("R: "); for(i=0;i<end+1;i++){ if(arr_p[i]==1000) printf("_ "); else printf("%d ",arr_p[i]); } printf("\r\n"); #endif while(arr_p[left]<=pivot){ left++; if(left>=right){//左边没有找到大于pivot的数退出总循环 arr_p[right] = pivot;//保存pivot到右边的坑里 flag = FALSE; break; } } if(flag){ //找到大于pivot的数移动到right arr_p[right] = arr_p[left]; arr_p[left] = 1000; right--; if(right<=left){ flag = FALSE; arr_p[left] = pivot;//当right左移等于left说明正好结束 } }else{ #if DEBUG printf("Rf: "); for(i=0;i<end+1;i++){ if(arr_p[i]==1000) printf("_ "); else printf("%d ",arr_p[i]); } printf("\r\n"); #endif break; } #if DEBUG printf("L: "); for(i=0;i<end+1;i++){ if(arr_p[i]==1000) printf("_ "); else printf("%d ",arr_p[i]); } printf("\r\n"); #endif } }
运行结果是:
这个例子比较特殊。一轮就得出结果了,但是实际上要对pivot左右两边都分别递归调用这个算法,才能得到从小到大的顺序。
这里递归判断的条件是:
Left<Right
左边下标大于或者等于右边下标的时候说明数字已经按照从小到大排列。
下面是快速排序的完整代码。
//快速排序 //left:数组的起始位 //right:数组的结束位置,注意不是数组的最大容量 void QuickSort(int * arr,int left,int right) { int pivotNum = 0; int start,end; if(left<right){ start = left,end = right; pivotNum = arr[start]; while(start<end){ //从右边找一个小于pivotNum的数 while(start<end && arr[end]>=pivotNum){ end--;//右边的游标左移 } if(start<end){ arr[start++] = arr[end]; } //从左边找一个大于pivotNum的数 while(start<end && arr[start]<=pivotNum){ start++;//左边的游标右移 } if(start<end){ arr[end--] = arr[start]; } } arr[start] = pivotNum;//这里在得出按照pivotNum比较得出顺序之后,要把中间数保存到最后游标停下的位置 QuickSort(arr,left,start-1); QuickSort(arr,start+1,right); } }
验证代码:
int main(int argc, char *argv[]) { int i=0; int arr[11] = {6,2,3,9,1,2,7,41,4,1,0}; QuickSort(arr,0,10); for(i=0;i<11;i++){ printf("%d ",arr[i]); } printf("\r\n"); system("pause"); return 0; }
运行结果:
最后对于pivotNum中间值的选择可以随机选择也可以去中间值。
快速排序的效率问题:
如果每次确定的中值都是最小或者最大,那么时间复杂度是O(N^2);
最好的情况是中值正好是中间值,那么时间复杂度是O(nlgN);
总结:就平均效率而言,快速排序是基于关键之比较的速度最快的,平均效率是O(nlgN);
时间: 2024-10-13 04:39:07