算法导论学习笔记(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);

    }

}

 

以上。

 

 

你可能感兴趣的:(partition)