marcus.x的博客

快速排序 - C语言

看了这本《数据结构与算法分析》中的快速排序。

写下自己理解后的代码,以备后用。

#include "stdio.h"

void insertSort(int arr[], int N)
{
    int j, tmp, P;
    for(P=1; P< N; P++)
    {
        tmp = arr[P];
        for(j=P; j>0 && arr[j-1] > tmp; j-- )
            arr[j] = arr[j-1];
        arr[j] = tmp;
    }
}

void swap(int *first, int *second)
{
    int tmp = *first;
    *first = *second;
    *second = tmp;
}

void printArr(int arr[], int N)
{
    int i;
    for( i = 0; i < N; i++)
    {
        printf("%d\t", arr[i]);
    }
    printf("\n");
}

int median3(int arr[], int left, int right)
{
    int mid = (left + right)/2;
    if(arr[left] > arr[mid])
        swap(&arr[left], &arr[mid]);
    if(arr[left] > arr[right])
        swap(&arr[left], &arr[right]);
    if(arr[mid] > arr[right])
        swap(&arr[mid], &arr[right]);

    swap(&arr[mid], &arr[right-1]);
    return arr[right -1];
}

void quickSort(int arr[], int left, int right)
{
    int coutoff = 3;
    if(left + coutoff < right)
    {
        int pivort = median3(arr, left, right);
        int i = left, j = right - 1;
        for(;;)
        {
            while(arr[++i] < pivort) {}
            while(arr[--j] > pivort) {}
            if(i < j)
                swap(&arr[i], &arr[j]);
            else
                break;
        }
        swap(&arr[i], &arr[right -1]);
        quickSort(arr, left, i - 1);
        quickSort(arr, i + 1, right);
    }
    else
    {
        insertSort(arr + left, right -left + 1);
    }
}

int main()
{
    int test[10] = {5, 1, 10, 44, 20, 199, 18, 7, 24, 42};
    printArr(test, 10);
    quickSort(test, 0, 9);
    // insertSort(test, 10)
    printArr(test, 10);
    return 0;
}
 
主要步骤:
1,首先要写好swap,写好插入排序。
2,然后写好选择哨兵(中间值)的代码 median3,并且要记得隐藏哨兵节点(交换 mid 和 right - 1),这样left, right -1 , right 就是已经排序的了, 这样第一个节点和最后一个节点就不用进行检查了。
3,左侧检查实际上从left + 1 开始,右侧检查实际上从right-2开始。当然为了++i, --j 方便, 并且查到要交换的位置就是i,j的值,设置了初值为左:left,右:right-1。
4,循环找左侧比哨兵大的值,右侧找并哨兵小的值,如果有则交换,如果循环到最后相遇了那么就表示没有可以交换的了,i 和 j 都走到合适的位置。此时i 的位置就是比哨兵大的第一个位置, j 的位置就是比哨兵小的第一个位置。
5, 一次排序结束后当然记得将哨兵放回去, 交换 i 和 right-1。
6,然后再从节点位置分成两部分排序。[left ~ i-1] 和[ i+1 ~ right]。
 
当元素小于三个的时候直接用插入排序。
注意问题:插入排序参数是数组长度,而快速排序的参数是左侧索引和右侧索引。
 
如果理解有错误,大家多指正。

posted on 2015-05-21 16:00  marcus.x  阅读(175)  评论(0编辑  收藏  举报

导航