数据结构-快速排序

1、快速排序(最好的内排序)

1)在待排序的元素任取一个元素作为基准(通常选第一个元素,但最好的选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;
2)将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;
3)对左右两个分区重复以上步骤直到所有元素都是有序的。

#include <stdio.h>
#include <stdlib.h>

void swap(int k[], int low, int high)
{
    int temp = k[low];
    k[low] = k[high];
    k[high] = temp;
}

//交换顺序表中子表顺序,返回枢纽所在的位置,此时在枢纽之前(不大于)后(不小于)
int Partition(int k[], int low, int high)
{
    int pivotkey;
    pivotkey = k[low]; //枢纽选取为第一个元素
    while (low < high)
    {
        while (low < high && k[high] >= pivotkey)//将右侧比枢纽小的值,调整至低端
            high--;
        swap(k, low, high);
        while (low < high && k[low] <= pivotkey)//将左侧比枢纽大的值,调整至高端
            low++;
        swap(k, low, high);
    }
    return low;//此时low=high,返回枢纽所在位置
}

void QuickSort(int k[], int low, int high)
{
    int pivot;
    if (low < high)
    {
        pivot = Partition(k, low, high);
        QuickSort(k, low, pivot - 1);   //对枢纽左侧递归排序
        QuickSort(k, pivot + 1, high);  //对枢纽右侧递归排序
    }
}

int main()
{
    int i;
    int a[10] = { 5, 2, 6, 0, 3, 9, 1, 7, 4, 8 };
    QuickSort(a, 0, 9);

    for (i = 0; i < 10; i++)
        printf_s("%d ", a[i]);

    return 1;
}

改进1:三数取中,取三个关键字先解析排序,将中间数作为枢轴,一般取左端,右端和中间三个数

如果我们选取的枢轴值正好是处于整个序列大小的中间位置,那么可以将序列分为小数集合和大数集合。但是若是我们第一个选取的是最大值呢?我们交换后实质变化并不大

int Partition(int k[], int low, int high)
{
    int pivotkey;
    int m = low + (high - low) / 2;
    //三数取中的判断
    if (k[low] > k[high])
        swap(k, low, high);
    if (k[m] > k[high])
        swap(k, m, high);
    if (k[m] < k[low])
        swap(k, m, low);
    //此时m处是三个数中间值

    pivotkey = k[m];    //用子表第一个记录左枢轴记录
    while (low < high)    //从表的两端交替向中间扫描
    {
        while (low < high && k[high] >= pivotkey)
            high--;
        swap(k, high, low);    //将比枢轴记录小的记录交换到低端
        while (low < high && k[low] <= pivotkey)
            low++;
        swap(k, low, high);    //将比枢轴记录大的记录交换到高端
    }
    return low;    //返回枢轴所在位置
}

改进二、优化小数组:当数组非常小时,使用快排还不如直接插入的性能好,二这个数组大小的阈值我们一般选取7最好

#define MAX_LENGTH_INSERT_SORT 7    //数组阈值大小

void InsertSort(int k[], int n)    //对数组部分进行快排
{
    int i, j, temp;
    for (i = 1; i < n;i++)
    {
        if (k[i]<k[i-1])
        {
            temp = k[i];
            for (j = i - 1; k[j] > temp; j--)
                k[j + 1] = k[j];
            k[j + 1] = temp;
        }
    }
}

void Qsort(int k[], int low, int high)
{
    int pivot;
    if ((high-low)>MAX_LENGTH_INSERT_SORT)    //条件是包含high>low
    {
        pivot = Partition(k, low, high);
        Qsort(k, low, pivot - 1);    //对低子表进行递归排序
        Qsort(k, pivot + 1, high);    //对高子表进行递归排序
    }
    else
    {
        InsertSort(k + low, high - low + 1);    //对数组部分进行快排
    }
}

 

posted @ 2020-03-05 22:56  kkzhang  阅读(414)  评论(0编辑  收藏  举报