快速排序
( 1)基本思想:
在当前无序区 R[1..H] 中任取一个数据元素作为比较的"基准"(不妨记为 X) ,用此基准将当前无序区划分为左右两个较小的无序区: R[1..I-1] 和 R[I+1..H] , 且左边的无序子区努力就有进步,坚持就能成功37中数据元素均小于等于基准元素, 右边的无序子区中数据元素均大于等于基准元素,而基准X 则位于最终排序的位置上, 即 R[1..I-1] ≤X.Key≤R[I+1..H](1≤I≤H) , 当 R[1..I-1] 和R[I+1..H] 均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止。
( 2)排序过程:
【示例】:
初 始 关键字 [49 38 65 97 76 13 27 49]
第一次交换后 〔27 38 65 97 76 13 49 49〕
第二次交换后 〔27 38 49 97 76 13 65 49〕
J 向左扫描, 位置不
变,第三次交换后 〔27 38 13 97 76 49 65 49〕
I 向右扫描, 位置不
变,第四次交换后 〔27 38 13 49 76 97 65 49〕
J 向左扫描 〔27 38 13 49 76 97 65 49〕
(一次划分过程)
初 始 关键字 〔 49 38 65 97 76 13 27 49〕
一趟排序之后 〔 27 38 13〕 49〔 76 97 65 49〕
二趟排序之后 〔 13〕 27〔 38〕 49〔 49 65〕 76〔 97〕
三趟排序之后 13 27 38 49 49〔 65〕 76 97
最后的排序结果 13 27 38 49 49 65 76 97
各趟排序之后的状态
快速排序算法 qsort
Const n=10;
Var a:array [1..n] of integer; k:integer;
努力就有进步,坚持就能成功
38
procedure qsort(low,high:integer);
var i,j:integer;x:integer;
begin
if low<high then
begin
i:=low;j:=high;x:=a[i];
repeat
while (a[j]>=x)and(i<j)do j:=j-1; {把大于基准的数留在右面}
if (a[j]<x)and(i<j) then
begin
a[i]:=a[j];i:=i+1; {把小于基准的数交换到左面}
end;
while (a[i]<=x)and (i<j) do i:=i+1;{把小于基准的数留在左面}
if (a[i]>x)and(i<j) then
begin
a[j]:=a[i];j:=j-1; {把大于基准的数交换到右面}
end;
until i=j; {直到 I 与 j 重叠, 完成一次分组过程}
a[i]:=x; {把基准数插入相应的位置, 以后不再参与排序}
qsort(low,i-1); {小于基准的数重复分组}
qsort(i+1,high); {大于基准的数重复分组}
end;
end;
算法改进:
procedure qsort(l,r:integer);
var i,j,mid:integer;
begin
i:=l;j:=r; mid:=a[(l+r) div 2]; {将当前序列在中间位置的数定义为中间数}
repeat
while a[i]<mid do inc(i); {在左半部分寻找比中间数大的数}
while a[j]>mid do dec(j); {在右半部分寻找比中间数小的数}
if i<=j then begin {若找到一组与排序目标不一致的数对则交换它们}
swap(a[i],a[j]);
inc(i);dec(j); {继续找}
end;
until i>j;
if l<j then qsort(l,j); {若未到两个数的边界,则递归搜索左右区间}
if i<r then qsort(i,r);
end;{sort}
从输出的数据可以发现, 对较坏的初始数据如第一组输入数据, 快速排序在交换数据的次数方面已给出了相当好的结果. 时间的复杂性是 O(nlog2n), 速度快, 但它也是不稳定的排序
『估计没有比我更神的了……刚才复制这东西去打印了……』