快速排序

oo

和归并排序一样, 快速排序也使用了分治思想(Divide & Conquer)

对一个数组进行快速排序, 通常分为三个步骤:

1. 分解: 数组a[p to r]被划分为两个可能为空的子数组a[p to q-1]和a[q to r], 使得a[p to q-1]中的每一个元素都<=a[q], 而a[q]也小于等于a[q+1 to r]中的每一个元素

2. 解决: 通过递归调用快速排序, 对子数组a[p to q-1]和a[q to r]进行排序.

3. 合并: 因为子数组是原址排序的, 所以不需要合并操作. 数组已经有序

 

快速排序中, 最核心的部分就是partition子过程: (假定采用升序排列)

首先以传入数组的最后一个元素为主元(pivot element), 从头遍历数组直到倒数第二个元素, 找到比pivot小的元素, 并且用一个计数器变量m来记录这种元素的个数. 每次遇到这种元素, 都把它交换到这列数组的第m位(相对位置), 并增加m.

结束遍历之后, 把第m位和最末位元素交换, 这样第m位左边的元素都比它小, 右边的元素都比它大(或等于). 返回第m位元素的绝对位置.

执行完partition操作, pivot element的”排名”就确定下来了, 永远不会再动.

我们再假设子数组的起始下标为from, 终止下标为to, 那么第m位元素的实际下标为from+m

 

附: 完整代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <stack>
#include <ctime>
using namespace std;
void quicksort(int* a, int from, int to);
void quicksort(int* a, int length);
int partition(int* a, int from, int to);

void quicksort(int* a, int from, int to)
{
    if (from<to)
    {
        int pivot = partition(a, from, to);
        quicksort(a, from, pivot-1);
        quicksort(a, pivot+1, to);
    }
}

void quicksort(int* a, int length)
{
    return quicksort(a,0,length-1);
}

int partition(int* a, int from, int to)
{
    int x = a[to];
    int i = from;
    for(int j = from; j<=to-1; ++j) {
        if (a[j]<=x)
        {
            swap(a[i],a[j]);
            ++i; 
        }
    }
    swap(a[i],a[to]);
    return i;
}

int main()
{
    int i[25] = {};
    srand(time(0));
    for (int k=0;k<25;++k)
        i[k] = rand()%103;
    quicksort(i,25);
    for(int j = 0; j<25; j++)
    {
        printf("%d ",i[j]);
    }
}
posted @ 2015-01-14 21:47  Roy_Mustango  阅读(329)  评论(0编辑  收藏  举报