当前位置:首页 » 操作系统 » 快排算法代码

快排算法代码

发布时间: 2022-07-23 18:10:38

1. 快速排序算法

快排这个算法对于初学者来说已经很难了,一个分治思想的递归算法对于初学者来说很难一次完成,如果你能成功说明已经有很强的编程能力了。不妨耐心的尝试一次,然后修改,然后再询问吧。

2. 关于算法 快排

网络快速排序就能够明白的事 还要求别人不复制。。。真弄不明白你

3. 求使用java实现的快排算法

① 代码:

publicclassquicksortdemo{

privateintarray[];
privateintlength;

publicvoidsort(int[]inputArr){

if(inputArr==null||inputArr.length==0){
return;
}
this.array=inputArr;
length=inputArr.length;
quickSort(0,length-1);
}

privatevoidquickSort(intlowerIndex,inthigherIndex){

inti=lowerIndex;
intj=higherIndex;
//calculatepivotnumber
intpivot=array[lowerIndex+(higherIndex-lowerIndex)/2];
//Divideintotwoarrays
while(i<=j){
while(array[i]<pivot){
i++;
}
while(array[j]>pivot){
j--;
}
if(i<=j){
swap(i,j);
i++;
j--;
}
}
//callquickSort()methodrecursively
if(lowerIndex<j)
quickSort(lowerIndex,j);
if(i<higherIndex)
quickSort(i,higherIndex);
}

privatevoidswap(inti,intj){
inttemp=array[i];
array[i]=array[j];
array[j]=temp;
}

publicstaticvoidmain(Stringa[]){

quicksortdemosorter=newquicksortdemo();
int[]input={24,2,45,20,56,75,2,56,99,53,12};
sorter.sort(input);
for(inti:input){
System.out.print(i);
System.out.print("");
}
}
}

② 运行:

c:>javaquicksortdemo
22122024455356567599

4. pascal快排,求源代码

找到你的安装目录 Fpc\demo\text,里面有一个qsort.pp,你用Fpc打开就是快排的源代码。快速排序又称划分交换排序。 它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键宇均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。具体做法是在当前无序区R[1]到R[h]中任取一个记录作为比较的“基准”(不妨记为temp), 用此基准将当前无序区划分为左右两个较小的无序子区:R[1]到R[i-1]和R[i+1]到R[h],且左边的无序子区中记录的关键字均小于或等于基准temp的关键字,右边的无序子区中记录的关键字均大于或等于基准temp的关键字,而基准temp则位于最终排序的位置上,即:R[1]到R[i-1]中关键字<=temp.key<=R[i+1]到R[h]的关键字(1<=i<=h)。当R[1]到R[i-1]和R[i+1]到R[h]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中记录均已排好序为止。下面是快速排序的过程。方括号表示无序区,上下划线表示基准temp的关键字,它未参加真正的交换,只是在划分完成时才将它放入正确的位置上。

初始关键字: [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对当前无序区R[1]到R[h]的划分具体做法:设置两个指针i和j,它们的初值分为i=1和j=h.不妨取基准为无序的第1个记录R[i](即R[1]),并将它保存在变量temp 中。令j自h起向左扫描,直到找到第1个关键字小于 temp.key的记录R[j],将R[j]移至i所指的位置上(这相当于交换了R[j]和基准R[i](即temp)的位置,使关键字小于基准关键字的记录移到了基准的左边);然后,令i自i+1起向右扫描,直至找到第1个关键字大于temp.key的记录R[i],将R[i]移至j指的位置上(这相当于交换了R[i]和基准R[j](即temp)的位置,使关键字大于基准关键字的记录移到了基准的右边);接着,令j自j-1起向左扫描,如此交替改变扫描方向,从两端各自往中间靠拢,直至i=j时,i便是基准temp的最终位置,将temp放在此位置上就完成了一次划分 。算法可描述如下:Procere Parttion(Var R : FileType; L, H : Integer; Var I : Integer);
{对无序区R[L,H]做划分,执行算法之后,求得I(L<=I<=H),I为本次划分后已被定位的基准元素的位置。若L<I,则R[L..I-1]中记录的关键字均不大于R[I]的关键字,若I<H,则R[I+1..H]中记录的关键字均不小于R[I]的关键字, }
Begin
I := L; J := H; temp:= R[I] ;{初始化,temp为基准元素}
Repeat
While (R[J] >=temp) And (I < J) Do
J := J - 1; {从右向左扫描,查找第一个小于 temp的元素}
If I < J Then {已找到R[J] 〈temp}
begin
R[I] := R[J]; {相当于交换R[I]和R[J]}
I := I + 1;
end;
While (R[I] <= temp) And (I < J) Do
I := I + 1 {从左向右扫描,查找第一个大于 temp的元素}
If I < J Then {已找到R[I] > temp }
begin R[J] := R[I]; {相当于交换R[I]和R[J]}
J := J - 1
end
Until I = J;
R[I] := temp {基准temp已被最终定位}
End; {Parttion }Procere QuickSort(Var R :FileType; S,T: Integer); {对R[S..T]快速排序}
Begin
If S < T Then {当R[S..T]为空或只有一个元素是无需排序}
begin
Parttion(R, S, T, I); {对R[S..T]做划分}
QuickSort(R, S, I-1);{递归处理左区间R[S,I-1]}
QuickSort(R, I+1,T);{递归处理右区间R[I+1..T] }
end;
End; {QuickSort}顺便再给你一个吧

5. 快速排序算法原理与实现

快速排序的原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。

然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:

1、设置两个变量I、J,排序开始的时候I:=1,J:=N;

2、以第一个数组元素作为关键数据,赋值给X,即X:=A[1];

3、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;

4、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;

5、重复第3、4步,直到I=J。

(5)快排算法代码扩展阅读:

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。

值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:

1、设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2、以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3、从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]的值赋给A[i];

4、从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]的值赋给A[j];

5、重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。

6. 求快速排序算法的代码

BOOL QuickSort(U16*p,int num)
{
int i;
int n_small=1,n_big=num-1;//升序
U16 m_key=p[0];
BOOL xiaokong=true;//小头有空
int m_free = 0;

if(num<=1)return true;///递归终止条件
for(i=0;i<num-1;i++)
{
if(xiaokong)//小头有空
{
if(p[n_big]<m_key)
{
p[m_free]=p[n_big];
m_free=n_big;
xiaokong=false;
}
n_big--;
}
else//大头有空
{
if(p[n_small]>m_key)
{
p[m_free]=p[n_small];
m_free=n_small;
xiaokong=true;
}
n_small++;
}
}
if(m_free != 0)
{
p[m_free]=m_key;
}
//printf("num=%d[", num);
//for( i = 0; i< num; i++) printf("%d,", p[i]);
//printf("]key=%d, mid = %d, small=%d, big=%d, from %d num %d && from %d num %d\n",
// m_key, m_free, n_small, n_big, 0,m_free, m_free+1, num-(m_free+1) );
if(QuickSort(&p[0],m_free) && QuickSort(&p[m_free+1],num-(m_free+1) ) )
{
return true;
}
return false;
}

void QuickSortTest(void)
{
int i;
U16 sortTest[20] = {23,4,6,9,5,7,4,12,12,23,4,9999,89,1000,1000,4,2334,989,12,20};
U16 sortTest2[10] = {10,9,8,7,6,5,4,3,2,1};
U16 sortTest3[10] = {0,1,2,3,4,5,6,7,8,9};
for( i = 0; i<20; i++) printf("%d,",sortTest[i]); printf("\n");
QuickSort( sortTest, 20);
for( i = 0; i<20; i++) printf("%d,",sortTest[i]); printf("\n");

for( i = 0; i<10; i++) printf("%d,",sortTest2[i]); printf("\n");
QuickSort( sortTest2, 10);
for( i = 0; i<10; i++) printf("%d,",sortTest2[i]); printf("\n");

for( i = 0; i<10; i++) printf("%d,",sortTest3[i]); printf("\n");
QuickSort( sortTest3, 10);
for( i = 0; i<10; i++) printf("%d,",sortTest3[i]); printf("\n");
}

7. C语言,快速排序算法

0和N-1表示的是数组下标。快排每一趟排序的目的是使值比设定的key值小的数都排到数组前部分,大的都排到后部分;然后对这两部分用新的关键值key分别重复上一步的操作;递归,直到数组有序。
其中关键值key=a[low]。
用题目给定的数组模拟第一趟排序如下:
下标0123456789
值91647824661232551
low=0high=9
part_element=a[low]=9
进入for循环
进入第一个while
part_element<51,于是high--,high=8;
part_element<25,high--,high=7;
part_element>3,不满足,结束while
a[low]=a[0]=a[high]=a[7]=3,low++,low=1;
进入第二个while
part_element<16,不满足,结束while
a[high]=a[7]=a[low]=a[1]=16,high--,high=6
for第一个循环结束,数组如下
316478246612162551
low=1,high=6
for第二个循环同上,结束时数组如下
344782476612162551
low=2,high=3
for第三个循环,第一个while中high--以后,low==high,直接break跳出for循环,此时
344782476612162551
low=2,high=2
结束for以后
a[high]=a[2]=part_element=9,得到
34982476612162551
split函数returnhigh=2

quicksort函数中middle=2;
下面两句递归,仍然是调用split函数,对数组
0-2,3-9两部分分别重复上述操作

最后直到数组数据有序

8. 快速排序算法的示例代码

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespacetest{classQuickSort{staticvoidMain(string[]args){int[]array={49,38,65,97,76,13,27};sort(array,0,array.Length-1);Console.ReadLine();}/**一次排序单元,完成此方法,key左边都比key小,key右边都比key大。**@paramarray排序数组**@paramlow排序起始位置**@paramhigh排序结束位置**@return单元排序后的数组*/privatestaticintsortUnit(int[]array,intlow,inthigh){intkey=array[low];while(low<high){/*从后向前搜索比key小的值*/while(array[high]>=key&&high>low)--high;/*比key小的放左边*/array[low]=array[high];/*从前向后搜索比key大的值,比key大的放右边*/while(array[low]<=key&&high>low)++low;/*比key大的放右边*/array[high]=array[low];}/*左边都比key小,右边都比key大。//将key放在游标当前位置。//此时low等于high*/array[low]=key;foreach(intiinarray){Console.Write({0} ,i);}Console.WriteLine();returnhigh;}/**快速排序*@paramarry*@return*/publicstaticvoidsort(int[]array,intlow,inthigh){if(low>=high)return;/*完成一次单元排序*/intindex=sortUnit(array,low,high);/*对左边单元进行排序*/sort(array,low,index-1);/*对右边单元进行排序*/sort(array,index+1,high);}}}运行结果:27 38 13 49 76 97 65
13 27 38 49 76 97 6513 27 38 49 65 76 97
快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示:
初始状态 {49 38 65 97 76 13 27} 进行一次快速排序之后划分为 {27 38 13} 49 {76 97 65} 分别对前后两部分进行快速排序{27 38 13} 经第三步和第四步交换后变成 {13 27 38} 完成排序。{76 97 65} 经第三步和第四步交换后变成 {65 76 97} 完成排序。图示 快速排序的最坏情况基于每次划分对主元的选择。基本的快速排序选取第一个元素作为主元。这样在数组已经有序的情况下,每次划分将得到最坏的结果。一种比较常见的优化方法是随机化算法,即随机选取一个元素作为主元。这种情况下虽然最坏情况仍然是O(n^2),但最坏情况不再依赖于输入数据,而是由于随机函数取值不佳。实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2^n)。所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。一位前辈做出了一个精辟的总结:“随机化快速排序可以满足一个人一辈子的人品需求。”
随机化快速排序的唯一缺点在于,一旦输入数据中有很多的相同数据,随机化的效果将直接减弱。对于极限情况,即对于n个相同的数排序,随机化快速排序的时间复杂度将毫无疑问的降低到O(n^2)。解决方法是用一种方法进行扫描,使没有交换的情况下主元保留在原位置。 QUICKSORT(A,p,r)
1if p<r
2then q ←PARTITION(A,p,r)
3QUICKSORT(A,p,q-1)
4QUICKSORT(A,q+1,r)
为排序一个完整的数组A,最初的调用是QUICKSORT(A,1,length[A])。
快速排序算法的关键是PARTITION过程,它对子数组A[p..r]进行就地重排:
PARTITION(A,p,r)
1x←A[r]
2i←p-1
3for j←p to r-1
4do if A[j]≤x
5then i←i+1
6exchange A[i]←→A[j]
7exchange A[i+1]←→A[r]
8return i+1 对PARTITION和QUICKSORT所作的改动比较小。在新的划分过程中,我们在真正进行划分之前实现交换:
(其中PARTITION过程同快速排序伪代码(非随机))
RANDOMIZED-PARTITION(A,p,r)
1i← RANDOM(p,r)
2exchange A[r]←→A[i]
3return PARTITION(A,p,r)
新的快速排序过程不再调用PARTITION,而是调用RANDOMIZED-PARTITION。
RANDOMIZED-QUICKSORT(A,p,r)
1if p<r
2then q← RANDOMIZED-PARTITION(A,p,r)
3RANDOMIZED-QUICKSORT(A,p,q-1)
4RANDOMIZED-QUICKSORT(A,q+1,r) 这里为方便起见,我们假设算法Quick_Sort的范围阈值为1(即一直将线性表分解到只剩一个元素),这对该算法复杂性的分析没有本质的影响。
我们先分析函数partition的性能,该函数对于确定的输入复杂性是确定的。观察该函数,我们发现,对于有n个元素的确定输入L[p..r],该函数运行时间显然为θ(n)。
最坏情况
无论适用哪一种方法来选择pivot,由于我们不知道各个元素间的相对大小关系(若知道就已经排好序了),所以我们无法确定pivot的选择对划分造成的影响。因此对各种pivot选择法而言,最坏情况和最好情况都是相同的。
我们从直觉上可以判断出最坏情况发生在每次划分过程产生的两个区间分别包含n-1个元素和1个元素的时候(设输入的表有n个元素)。下面我们暂时认为该猜测正确,在后文我们再详细证明该猜测。
对于有n个元素的表L[p..r],由于函数Partition的计算时间为θ(n),所以快速排序在序坏情况下的复杂性有递归式如下:
T(1)=θ(1),T(n)=T(n-1)+T(1)+θ(n) (1)
用迭代法可以解出上式的解为T(n)=θ(n2)。
这个最坏情况运行时间与插入排序是一样的。
下面我们来证明这种每次划分过程产生的两个区间分别包含n-1个元素和1个元素的情况就是最坏情况。
设T(n)是过程Quick_Sort作用于规模为n的输入上的最坏情况的时间,则
T(n)=max(T(q)+T(n-q))+θ(n),其中1≤q≤n-1 (2)
我们假设对于任何k<n,总有T(k)≤ck,其中c为常数;显然当k=1时是成立的。
将归纳假设代入(2),得到:
T(n)≤max(cq2+c(n-q)2)+θ(n)=c*max(q2+(n-q)2)+θ(n)
因为在[1,n-1]上q2+(n-q)2关于q递减,所以当q=1时q2+(n-q)2有最大值n2-2(n-1)。于是有:
T(n)≤cn2-2c(n-1)+θ(n)≤cn2
只要c足够大,上面的第二个小于等于号就可以成立。于是对于所有的n都有T(n)≤cn。
这样,排序算法的最坏情况运行时间为θ(n2),且最坏情况发生在每次划分过程产生的两个区间分别包含n-1个元素和1个元素的时候。
时间复杂度为o(n2)。
最好情况
如果每次划分过程产生的区间大小都为n/2,则快速排序法运行就快得多了。这时有:
T(n)=2T(n/2)+θ(n),T(1)=θ(1) (3)
解得:T(n)=θ(nlogn)
快速排序法最佳情况下执行过程的递归树如下图所示,图中lgn表示以10为底的对数,而本文中用logn表示以2为底的对数.
由于快速排序法也是基于比较的排序法,其运行时间为Ω(nlogn),所以如果每次划分过程产生的区间大小都为n/2,则运行时间θ(nlogn)就是最好情况运行时间。
但是,是否一定要每次平均划分才能达到最好情况呢?要理解这一点就必须理解对称性是如何在描述运行时间的递归式中反映的。我们假设每次划分过程都产生9:1的划分,乍一看该划分很不对称。我们可以得到递归式:
T(n)=T(n/10)+T(9n/10)+θ(n),T(1)=θ(1) (4)
请注意树的每一层都有代价n,直到在深度log10n=θ(logn)处达到边界条件,以后各层代价至多为n。递归于深度log10/9n=θ(logn)处结束。这样,快速排序的总时间代价为T(n)=θ(nlogn),从渐进意义上看就和划分是在中间进行的一样。事实上,即使是99:1的划分时间代价也为θ(nlogn)。其原因在于,任何一种按常数比例进行划分所产生的递归树的深度都为θ(nlogn),其中每一层的代价为O(n),因而不管常数比例是什么,总的运行时间都为θ(nlogn),只不过其中隐含的常数因子有所不同。(关于算法复杂性的渐进阶,请参阅算法的复杂性)
平均情况
快速排序的平均运行时间为θ(nlogn)。
我们对平均情况下的性能作直觉上的分析。
要想对快速排序的平均情况有个较为清楚的概念,我们就要对遇到的各种输入作个假设。通常都假设输入数据的所有排列都是等可能的。后文中我们要讨论这个假设。
当我们对一个随机的输入数组应用快速排序时,要想在每一层上都有同样的划分是不太可能的。我们所能期望的是某些划分较对称,另一些则很不对称。事实上,我们可以证明,如果选择L[p..r]的第一个元素作为支点元素,Partition所产生的划分80%以上都比9:1更对称,而另20%则比9:1差,这里证明从略。
平均情况下,Partition产生的划分中既有“好的”,又有“差的”。这时,与Partition执行过程对应的递归树中,好、差划分是随机地分布在树的各层上的。为与我们的直觉相一致,假设好、差划分交替出现在树的各层上,且好的划分是最佳情况划分,而差的划分是最坏情况下的划分。在根节点处,划分的代价为n,划分出来的两个子表的大小为n-1和1,即最坏情况。在根的下一层,大小为n-1的子表按最佳情况划分成大小各为(n-1)/2的两个子表。这儿我们假设含1个元素的子表的边界条件代价为1。
在一个差的划分后接一个好的划分后,产生出三个子表,大小各为1,(n-1)/2和(n-1)/2,代价共为2n-1=θ(n)。一层划分就产生出大小为(n-1)/2+1和(n-1)/2的两个子表,代价为n=θ(n)。这种划分差不多是完全对称的,比9:1的划分要好。从直觉上看,差的划分的代价θ(n)可被吸收到好的划分的代价θ(n)中去,结果是一个好的划分。这样,当好、差划分交替分布划分都是好的一样:仍是θ(nlogn),但θ记号中隐含的常数因子要略大一些。关于平均情况的严格分析将在后文给出。
在前文从直觉上探讨快速排序的平均性态过程中,我们已假定输入数据的所有排列都是等可能的。如果输入的分布满足这个假设时,快速排序是对足够大的输入的理想选择。但在实际应用中,这个假设就不会总是成立。
解决的方法是,利用随机化策略,能够克服分布的等可能性假设所带来的问题。
一种随机化策略是:与对输入的分布作“假设”不同的是对输入的分布作“规定”。具体地说,在排序输入的线性表前,对其元素加以随机排列,以强制的方法使每种排列满足等可能性。事实上,我们可以找到一个能在O(n)时间内对含n个元素的数组加以随机排列的算法。这种修改不改变算法的最坏情况运行时间,但它却使得运行时间能够独立于输入数据已排序的情况。
另一种随机化策略是:利用前文介绍的选择支点元素pivot的第四种方法,即随机地在L[p..r]中选择一个元素作为支点元素pivot。实际应用中通常采用这种方法。
快速排序的随机化版本有一个和其他随机化算法一样的有趣性质:没有一个特别的输入会导致最坏情况性态。这种算法的最坏情况性态是由随机数产生器决定的。你即使有意给出一个坏的输入也没用,因为随机化排列会使得输入数据的次序对算法不产生影响。只有在随机数产生器给出了一个很不巧的排列时,随机化算法的最坏情况性态才会出现。事实上可以证明几乎所有的排列都可使快速排序接近平均情况性态,只有非常少的几个排列才会导致算法的近最坏情况性态。
一般来说,当一个算法可按多条路子做下去,但又很难决定哪一条保证是好的选择时,随机化策略是很有用的。如果大部分选择都是好的,则随机地选一个就行了。通常,一个算法在其执行过程中要做很多选择。如果一个好的选择的获益大于坏的选择的代价,那么随机地做一个选择就能得到一个很有效的算法。我们在前文已经了解到,对快速排序来说,一组好坏相杂的划分仍能产生很好的运行时间 。因此我们可以认为该算法的随机化版本也能具有较好的性态。

热点内容
宽屏企业网站源码 发布:2025-01-20 05:55:54 浏览:451
局域网电脑访问权限 发布:2025-01-20 05:55:44 浏览:823
javaandroid游戏开发 发布:2025-01-20 05:54:19 浏览:72
数据库映射是什么 发布:2025-01-20 05:41:52 浏览:981
中国植物数据库 发布:2025-01-20 05:38:50 浏览:334
C语言能吗 发布:2025-01-20 05:37:25 浏览:558
onedrive存储位置 发布:2025-01-20 05:35:16 浏览:826
导航广播怎么存储电台 发布:2025-01-20 05:35:14 浏览:310
歌的压缩包 发布:2025-01-20 05:23:53 浏览:391
如何通过服务器ip查到电话 发布:2025-01-20 05:02:34 浏览:8