快速排序

来源:互联网 发布:网络优化课程 编辑:程序博客网 时间:2024/05/01 16:12

        快速排序(Quicksort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

       快速排序是一种内部排序方法。也就是说快速排序的排序对象是读入内存的数据。
       但是快速排序是一种不稳定的排序方法。简单地说,元素a1, a2的关键字有a1.key=a2.key,则不稳定的排序方法不能保证a1, a2在排序后维持原来的位置先后关系。
       快速排序每次将待排序数组分为两个部分,在理想状况下,每一次都将待排序数组划分成等长两个部分,则需要logn次划分。而在最坏情况下,即数组已经有序或大致有序的情况下,每次划分只能减少一个元素,快速排序将不幸退化为冒泡排序,所以快速排序时间复杂度下界为O(nlogn),最坏情况为O(n^2)。在实际应用中,快速排序的平均时间复杂度为O(nlogn)。
    参考不少资料算写完两个程序:

       程序1

#include<stdio.h>void QuickSort(int e[],int low,int high){int i=low,j=high,temp=e[low];while(i<j){while(i<j&&e[j]>=temp)j--;e[i]=e[j];while(i<j&&e[i]<=temp)i++;e[j]=e[i];}e[i]=temp;if(low<i-1){QuickSort(e,low,i-1);}if(high>i+1){QuickSort(e,i+1,high);}}void main(){int array[100],a,len;char ch;printf("请输入待排数据(不超过100个),以空格间隔、回车键结束\n");for(a=0;;a++){scanf("%d%c",&array[a],&ch);if(ch==10)break;}printf("排序前:");len=a+1;//因为数组下表从0开始,所以数组长度为最大下标加1for(int i=0;i<len;i++)printf("%d ",array[i]);QuickSort(array,0,len-1);printf("\n排序后:");for(i=0;i<len;i++)printf("%d ",array[i]);printf("\n");}


         程序2(参考《数据结构》(C语言版)):

 // DataType.h 待排记录的数据类型#define MAXSIZE 20 //一个用作示例的小顺序的最大长度typedef int KeyType;//定义关键字类型为整数类型typedef int InfoType;//定义其他类型typedef struct{KeyType key;//关键字项InfoType otherInfo;//其他数据项}RedType; //记录类型typedef struct{RedType r[MAXSIZE+1];//r[0]闲置或用作哨兵单元int length;//顺序表的长度}SqList;//顺序表类型

 

/** *QuickSort *参考《数据结构》(C语言版) */#include<stdio.h>#include"DataType.h"int Partition(SqList &L,int low,int high){//交换顺序表L中子表r[low...high]的记录,枢轴记录到位,并返回其所在位置,//此时在它之前(后)的记录均不大(小)于它KeyType pivotKey; L.r[0]=L.r[low];//用子表的第一个记录作枢轴记录pivotKey=L.r[low].key;//枢轴记录关键字while(low<high){//从表的两端交替的向中间扫描while(low<high&&L.r[high].key>=pivotKey)--high;L.r[low]=L.r[high];while(low<high&&L.r[low].key<=pivotKey)++low;L.r[high]=L.r[low];}L.r[low]=L.r[0];return low;//返回枢轴位置}//Partitionvoid QSort(SqList &L,int low,int high){//对顺序表L中的子序列L.[low...high]作快速排序int pivotLoc;if(low<high){pivotLoc=Partition(L,low,high);//将L.[low...high]一分为二QSort(L,low,pivotLoc-1);QSort(L,pivotLoc+1,high);}}//QSortvoid QuickSort(SqList &L){//对顺序表L作快速排序QSort(L,1,L.length);}//QuickSortvoid print(SqList &L){int i;for(i=1;i<=L.length;i++){printf("(%d,%d)",L.r[i].key,L.r[i].otherInfo);}printf("\n");}//Print#define N 8  void main() {   RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}};   SqList l;   int i;   for(i=0;i<N;i++)     l.r[i+1]=d[i];   l.length=N;   printf("排序前:\n");   print(l);   QuickSort(l);   printf("排序后:\n");   print(l); } 

快速排序需要一个栈空间来实现递归, 若每一趟排序都将记录序列均匀地分割成长度相接近的两个子序列,则栈的最大深度为[log2n]+1(以2为底)(包括最外层参量进栈),但是,若每趟排序之后,枢轴位置均偏向子序列的一端,则为最坏情况,栈的最大深度为n,如果 在一趟排序之后比较分割所得两部分的长度,且先对长度短的子序列中的记录进行快速排序,则栈的最大深度可降为O(logn)。

原创粉丝点击