快速排序及其改进

#include<iostream>
#include<ctime>
using namespace std;
void InsertSort(int* arr, int begin, int end)
{
    for (int i = begin; i <= end; i++)
    {
        int j = begin;
        while (arr[i] > arr[j])
        {
            j++;
        }
        int temp = arr[i];
        for (int k = i; k >= j; k--)
        {
            arr[k] = arr[k - 1];
        }
        arr[j] = temp;
    }
}
void Swap(int& a, int& b)
{
    int temp = a;
    a = b;
    b = temp;
}
void QuickSortCore(int* arr, int begin, int end)
{
    if (begin>=end)
    {
        return;
    }
    int pivot = arr[begin];
    Swap(arr[begin], arr[end]);
    int left = begin - 1;
    int right = end;
    while (left < right)
    {
        do
        {
            left++;
        } while (arr[left] < pivot);
        do
        {
            right--;
        } while (arr[right] > pivot);
        if (left < right)
        {
            Swap(arr[left], arr[right]);
        }
    }
    Swap(arr[left], arr[end]);
    QuickSortCore(arr, begin, left - 1);
    QuickSortCore(arr, left + 1, end);
}
void QuickSort(int* arr, int len)
{
    if (arr == nullptr || len <= 0)
    {
        return;
    }
    QuickSortCore(arr, 0, len - 1);
}
static const int len = 100000;
int main()
{
    int arr[len];
    for (int i = 0; i < len; i++)
    {
        arr[i] = rand() % len;
    }
    clock_t start = clock();
    QuickSort(arr, len);
    clock_t end = clock();
    cout << "sort " << len << " num with original quicksort cost " << (double)(end - start) / CLOCKS_PER_SEC << "seconds"<<endl;
    /*for (int i = 0; i < len; i++)
    {
        cout << arr[i] << "  ";
    }*/
    return 0;
}

运行时间

改进1:待排序数目小于某个值时改用插入排序,这里取10

void InsertSort(int* arr, int begin, int end)
{
    for (int i = begin; i <= end; i++)
    {
        int j = begin;
        while (arr[i] > arr[j])
        {
            j++;
        }
        int temp = arr[i];
        for (int k = i; k >= j; k--)
        {
            arr[k] = arr[k - 1];
        }
        arr[j] = temp;
    }
}

原快速排序改成

void QuickSortCore(int* arr, int begin, int end)
{
    if (end-begin<10)
    {
        InsertSort(arr, begin, end);
        return;
    }
    int pivot = arr[begin];
    Swap(arr[begin], arr[end]);
    int left = begin - 1;
    int right = end;
    while (left < right)
    {
        do
        {
            left++;
        } while (arr[left] < pivot);
        do
        {
            right--;
        } while (arr[right] > pivot);
        if (left < right)
        {
            Swap(arr[left], arr[right]);
        }
    }
    Swap(arr[left], arr[end]);
    QuickSortCore(arr, begin, left - 1);
    QuickSortCore(arr, left + 1, end);
}

运行时间如下
这里写图片描述
可以看到,运行时间比原快速排序少了一点

改进2:原支点值我们选的是待排序段的第一个值,当这个值选得不好的时候,排序效果很差,这里我们采用三值取中原则选取支点。

int MedianOfThree(int* arr, int begin, int end)
{
    int index;
    int median = (begin + end) / 2;

    int sum = arr[begin] + arr[median] + arr[end];
    int max=0x80000000, min=0x7fffffff;
    if (arr[begin] > arr[median])
    {
        max = arr[begin];
        min = arr[median];
    }
    if (max < arr[end])
    {
        max = arr[end];
    }
    if (min > arr[end])
    {
        min = arr[end];
    }

    int med = sum - max - min;
    if (med == arr[begin])
    {
        index = begin;
    }
    else if (med == arr[median])
    {
        index = median;
    }
    else
    {
        index = end;
    }
    return index;
}

原排序代码改成

void QuickSortCore(int* arr, int begin, int end)
{
    if (end-begin<10)
    {
        InsertSort(arr, begin, end);
        return;
    }
    int pivot_index = MedianOfThree(arr,begin,end);
    int pivot = arr[pivot_index];

    Swap(arr[pivot_index], arr[end]);
    int left = begin - 1;
    int right = end;
    while (left < right)
    {
        do
        {
            left++;
        } while (arr[left] < pivot);
        do
        {
            right--;
        } while (arr[right] > pivot);
        if (left < right)
        {
            Swap(arr[left], arr[right]);
        }
    }
    Swap(arr[left], arr[end]);
    QuickSortCore(arr, begin, left - 1);
    QuickSortCore(arr, left + 1, end);
}

运行时间
这里写图片描述
运行时间并没有显著的变化,又不能取更大的运算规模,因为会栈溢出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值