一、快速排序算法:QuickSort
public void QuickSort(SeqList R,int low,int high){
//对R[low...high]进行快速排序
int pivotpos;//划分后的基准记录的位置
if(low<high){
//仅当区间长度大于1时才需排序
pivotpos = Partition(R,low,high);//对R[low...high]进行划分
QuickSort(R,low,pivotpos-1);
QuickSort(R,pivotpos+1,high);
}
}
二、划分算法:Paitition
(1)简单的划分算法
【1】具体做法:
第一步:设置两个指针,i和j,它们的初值分别为区间的上界和下界,即i=low,j=high;选取无序区的第一个记录R[i](即R[low])作为基准记录,并把它保存在pivot中;
第二部:令j自high起向左扫描,直到找到第一个关键字小于pivot.key的记录R[j].将R[j]移至i所指的位置上,使关键字小于基准关键字pivot.key的记录移到了基准的左边,然后令i指针自i+1位置开始向右扫描,直到找到第一个关键字大于pivot.key的记录R[i],将R[i]移到了j所指向的位置,使关键字大于基准关键字的记录移到了基准的右边。接着令指针j自位置j-1开始向左扫描。如此交替改变扫描方向,从两端各自往中间靠拢,直至i=j时,i便是基准pivot最终的位置,将pivot放在此位置上就完成了一次划分。
这里有个此方法的在线演示:
你也许会看的糊涂,和网上流传的不太一样#^_^#。我们来看下网上流传的:
假如有这样一组数字:
2,4,22,12,0,3,4
①首先令i指向第一个记录,j指向最后一个记录,取第一个数字为基准数字pivot = R[i] 即为 2
② 使用j从右向左开发扫描,直到找到第一个关键字小于pivot.key的记录R[j].将R[j]移至i所指的位置上的关键字互换位置,即做了一次数据交换。此步执行后这组数字变为:
0,4,22,12,2,3,4
③i从i+1位置开始向右扫描,直到找到第一个关键字大于pivot.key的记录R[i].将R[i]移至j所指向的位置上的关键字互换位置,即做了一次数据交换。此步执行后这组数字变为:
0,2,22,12,4,3,4
④j从j-1的位置开始向左扫描,直到找到第一个关键字小于pivot.key的记录R[j],等i==j的时候没找到,此时,一趟快速排序结束。这组数字为0,2,22,12,4,3,4
你会发现,网上的这个算法和上文中的算法,最大的区别就是标红字的地方,网上的是互换位置,而上文中的算法是一次赋值,无疑,当数据量大时,网上流传的这个算法耗费了大量性能。
【2】划分算法伪代码:
public int Partition(SeqList R,int i,int j){
//调用Partition(R,low,high)时,对R[low...high]进行划分
//并返回基准记录的位置
dataType pivot = R[i];//用区间的第1个记录作为基准,
while(i<j){//从区间两段交替向中间扫描,直至i==j为止
while(i<j&&R[j].key>=pivot.key){
--j;//从右向左扫描,查找第1个关键字小于pivot.key的记录R[j]
}
if(i<j){//表示找到的R[j]的关键字<pivot.key
R[i++]= R[j];//注意,是i++,相当于R[i]=R[j];++i;R[j]给R[i],然后i指针加1
}
while(i<j&&R[i].key<=pivot.key){
++i;
}
if(i<j){//表示找到了R[i],使R[i].key>pivot.key
R[j--]=R[i];//注意,这里是j--
}
}//endWhile
R[i]=pivot;//基准位置被最后定为,当i==j的时候
return i;
}