算法导论学习笔记(1)——快排中hoarePartition的实现(问题已解决)
打算在学期结束之前(1月19日)看完,目前94页,总共六百页,不完全做习题及思考题(不细致考虑各种时间)。
之所以发表这个是公开一下,算是对自己的监督吧。以下进入正题
实现各种算法时都OK,在快速排序这里第一次遇到问题,算法出错,hoarePartition是快速排序中用到的一个比较古老的分块算法。
伪代码
HOARE-PARTITION(A,p,r)
{
x=A[p]
i=p-1
j=r+1
while(1)
{
do repeat j--
until A[j]<=x
repeat i++
until A[i]>=x
if i<j
then exchange A[i] and A[j]
else return j
}
}
思维比较清晰的算法,当同时找到坐标x两端的异常值时,左右互换
C代码
1 #include <stdio.h> 2 3 void RandomDoSort(int A[],int begin,int end); 4 int Hoare_Partition(int A[],int begin,int end); 5 6 void ChangeTwoInt(int* a,int* b); 7 8 void main() 9 { 10 int A[12]={13,19,9,5,12,8,7,4,21,2,6,11}; 11 RandomDoSort(A,0,11); 12 for (int i=0;i<12;i++) 13 { 14 printf("%d\n",A[i]); 15 } 16 } 17 18 19 void RandomDoSort(int A[],int begin,int end) 20 { 21 int q=0; 22 if(begin<end) 23 { 24 q=Hoare_Partition(A,begin,end); 25 DoSort(A,begin,q-1); 26 DoSort(A,q+1,end); 27 } 28 } 29 30 int Hoare_Partition(int A[],int begin,int end) 31 { 32 int xtemp=A[begin]; 33 int i=begin-1; 34 int j=end+1; 35 while (1) 36 { 37 j--; 38 if (A[j]<=xtemp) 39 { 40 while(A[i]<xtemp) 41 { 42 i++; 43 } 44 } 45 if (i<j) 46 { 47 ChangeTwoInt(&A[i],&A[j]); 48 } 49 else 50 { 51 return j; 52 } 53 } 54 } 55 56 void ChangeTwoInt(int* a,int* b) 57 { 58 int temp=*a; 59 *a=*b; 60 *b=temp; 61 }
最后结果出错,有一个数没排序上,睡觉去,明早起来调试解决这问题
其实问题并不出在Partition这个函数里,而是在Dosort函数里。上面这个Dosort函数简单地修改了之前另一个Partition搭配的Dosort,两者思想有细微区别。
先来看之前的Partition。
int Partition(int A[],int begin,int end) { int x=A[end]; int i=begin-1; int temp=0; for(int j=begin;j<=end-1;j++) { if(A[j]<x) { i++; temp=A[j]; A[j]=A[i]; A[i]=temp; } } temp=A[i+1]; //将坐标轴元素放在排序好的位置上 A[i+1]=A[end]; A[end]=temp; return i+1; }
再来看HoarePartition
int Hoare_Partition(int A[],int begin,int end) { int xtemp=A[begin]; int i=begin-1; int j=end+1; while (1) { j--; if (A[j]<=xtemp) { while(A[i]<xtemp) { i++; } } if (i<j) { ChangeTwoInt(&A[i],&A[j]); } else { return j; } } }
两者的区别是:前面那种在Partition过程中就将坐标轴元素放在排序好的位置上,自然在DOsort的迭代过程中不用再考虑该元素,但Hoare则没有这样做,在Hoare匹配的Dosort迭代时自然要将该元素也纳入迭代的考虑范围。
来看两个Dosort
之前那一种
void DoSort(int A[],int begin,int end) { int q=0; if(begin<end) { q=Partition(A,begin,end); DoSort(A,begin,q-1); //A[q]不需要再处理 DoSort(A,q+1,end); } }
Hoare对应的Dosort
void HoareDoSort(int A[],int begin,int end) { int q=0; if(begin<end) { q=Hoare_Partition(A,begin,end); DoSort(A,begin,q); //需要对A[q]再处理 DoSort(A,q+1,end); } }
以上。