QuickSort

Read Hoar's article "quicksort" published in "the computer journal". Try to understand quicksort algorithm further.

I.Stratgy:
The quicksort is based on the principle of resolving a problem into two simpler subproblems. Each of these subproblems may be resolved to produce yet simpler problems. The proccess is repeated until all the resulting problems are found to be trivial problem.


If there is a dividing line, the keys of all the items held in the locations lower than the divding line are less than the keys of all the items held in locations above this diving line,  the two segments may be sorted separately in this case, and as a result the whole mass of data will be sorted.

II.How to bring into the dividing line?
 use the partition method.
 i. Firstly, choose a particularly key value which is known to be within the range of the key of all itmes they are to be sorted. A simple method is to choose the actual key valie of one of the itmes. The chosen key value will be called bound.

ii. Scan all the itmes to make all the itmes be separated by the bound. Use two pointer. One is the lower pointer, starts at the itme with the lowest address. and another is uppper positon, starts at the itme with the uppest address. Lower pointer move upward until it finds an item whose key value is greater than the bound. Then the upper pointer move downward until it finds an itme whose key value is lower than the boud. Now the two items to which the two pointers refer are obviously in the wrong positions, and they must be exchanged. After the exchang, continue the process until the two pointers cross each other. The lower point refers to a item in a higher-addressed
location than the itme referred by the upper point. The process ends. Then the dividing line is between lower point and upper point.


iii. A awkward situation may happen according to the above rule, if the bound is the greatest or least of all the key values in a segment. Firstly, I think if we can relove the issue by changing the above rule. I change the stop standard from "greater than" or "lower than" into "greater than or equal to " or "lower than or equal to". But I realize that the changing cannot work if both the key value of lowest address item and the one of  uppest address item equal to bound. In this case, an infinite cycle results (Later, I search other algorithm and find the issue can be avoided by increasing lower and descreasing upper explicitly). C.A.R. Hoare explained that the situation can be prevented by making sure that one item at least is in a correct position as a result of each application of the partitioning process. So we can make sure that the bound is in correct location when it is the greatest or lowest. Compate the key value of lowest address item to the one of uppest address item. If greater, then switch the two items. then continue the step ii.

I write a partition program according to the description.

template<typename T>
void swap(T*a,T*b){
    T temp;
    temp = *b;
    *b = *a;
    *a = temp;
}

template <typename T>
int Partition(T array[], int lower, int upper){
    T pivot = array[lower];
    int orgLower = lower;
    int orgUpper = upper;

    if(array[lower]>array[upper]){
        swap(array+lower,array+upper);
    }

    while(lower<upper){
        while(array[lower]<=pivot && lower<orgUpper){
            ++lower;
        }

        while(array[upper]>=pivot && upper>orgLower){
            --upper;
        }

        if(lower < upper){
            swap(array+lower,array+upper);
        }
    }
    return upper;
}


A other partition program is:

template <typename T>
int Partition(T array[], int lower, int upper){
    T pivot = array[lower];
  
    while(lower<upper){
        while(array[lower]<pivot && lower<orgUpper){
            ++lower;
        }

        while(array[upper]>pivot && upper>orgLower){
            --upper;
        }

        if(lower < upper){
            swap(array+lower,array+upper);
        }
    }
    return upper;
}

If the items in a segment to be sorted are equal, there are many redundant exchanings using Partition2.

Because the dividing line is NOT an elment, we have to write the quicksort recursion function in the next way.


template <typename T>
void QuickSort_NoEle_Dvd(T array[], int lower, int upper){
    if(lower<upper){
        int pos = Partition(array,lower,upper);
        QuickSort_NoEle_Dvd(array,lower,pos); //the lower address segment include the element at the left of the dividing line.
        QuickSort_NoEle_Dvd(array,pos+1,upper);
    }
}

III. Other good partition program.

template <typename T>
int Partition(T array[], int lower, int upper){
    T pivot = array[lower];

    while(lower<upper){
        while(lower<upper && array[upper]>=pivot){
            --upper;
        }
        if(lower != upper){
            swap(array+lower,array+upper);
        }

        while(lower<upper && array[lower]<=pivot){ //内部两个while循环中,必须有一个判断条件中包含=。
            ++lower;                               //两个都包含=可以减少一些交换。
        }
        if(lower != upper){
            swap(array+lower,array+upper);
        }
    }
    return lower;
}

The above  program is the best program in these partition programs.

template <typename T>
int Partition3(T array[], int lower, int upper){
    T pivot = array[lower];
    swap(array+lower,array+upper);
    int strInd = lower;
    for(int i=lower; i<upper; i++){
        if(array[i] <= pivot){
            swap(array+i,array+strInd);//存在一些无谓的交换
            ++strInd;
        }
    }
    swap(array+upper,array+strInd);
    return strInd;
}

One element is dividing line, so we can write recursiong quick sort function in anthoer way:
template <typename T>
void QuickSort_Ele_Dvd(T array[], int lower, int upper){
    if(lower<upper){
        int pos = Partition(array,lower,upper);
        QuickSort_Ele_Dvd(array,lower,pos-1);
        QuickSort_Ele_Dvd(array,pos+1,upper);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值