走进数据结构和算法(c++版)(20)——排序(3)

排序(3)

  这一章中我们将主要介绍下快速排序,并对这几章的排序算法进行总结。

1.快速排序

  快速排序( Quick Sort) 的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

#include<iostream>
#include<vector>
using namespace std;

void QuickSort(vector<int>& vec);//快速排序
void QSort(vector<int>& vec, int low, int high);
int  Partition(vector<int>& vec, int low, int high);
int main()
{
    int n,e;
    vector<int> vec;
    cout << "输入数据元素个数:" << endl;
    cin >> n;
    cout << "输入数据元素:" << endl;
    for (int i = 0; i < n; i++)
    {
        cin >> e;
        vec.push_back(e);
    }
    QuickSort(vec);
    cout << "从小到大排序结果:" << endl;
    for (int i = 0; i < n; i++)
    {
        cout << vec[i] << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}
void QuickSort(vector<int>& vec)//快速排序
{
    QSort(vec, 0, vec.size()-1);
}
void QSort(vector<int>& vec,int low ,int high)
{
    int pivot;
    if (low < high)
    {
        pivot = Partition(vec,low,high);

        QSort(vec, low, pivot - 1);
        QSort(vec, pivot + 1, high);

    }
}
int  Partition(vector<int>& vec, int low, int high)
{
    int pivotkey;
    pivotkey = vec[low];
    while (low < high)
    {
        while (low < high&&vec[high] >= pivotkey)
            high--;
        swap(vec[low], vec[high]);
        while (low < high&&vec[low] <= pivotkey)
            low++;
        swap(vec[low], vec[high]);

    }
    return low;
}

  在VS上运行结果如下:
1

2.快速排序优化

2.1优化选取枢轴

  取三个关键字先进行排序,将中间数作为枢轴, 一般是取左端、右端和中间三个数, 也可以随机选取。

int  Partition(vector<int>& vec, int low, int high)
{
    int pivotkey;

    /*优化选取枢轴*/
    int m = low + (high - low) / 2;
    if (vec[low]>vec[high])
        swap(vec[low], vec[high]);
    if (vec[m] > vec[high])
        swap(vec[m], vec[high]);
    if (vec[m] > vec[low])
        swap(vec[m], vec[low]);

    pivotkey = vec[low];
    while (low < high)
    {
        while (low < high&&vec[high] >= pivotkey)
            high--;
        swap(vec[low], vec[high]);
        while (low < high&&vec[low] <= pivotkey)
            low++;
        swap(vec[low], vec[high]);

    }
    return low;
}

2.2优化不必要的交换

  

int  Partition(vector<int>& vec, int low, int high)
{
    int pivotkey;

    /*优化选取枢轴*/
    int m = low + (high - low) / 2;
    if (vec[low]>vec[high])
        swap(vec[low], vec[high]);
    if (vec[m] > vec[high])
        swap(vec[m], vec[high]);
    if (vec[m] > vec[low])
        swap(vec[m], vec[low]);

    pivotkey = vec[low];

    int e = pivotkey;//将枢轴关键字备份
    while (low < high)
    {
        while (low < high&&vec[high] >= pivotkey)
            high--;
        //swap(vec[low], vec[high]);
        e = vec[high];//采用替换代替交换

        while (low < high&&vec[low] <= pivotkey)
            low++;
        //swap(vec[low], vec[high]);
        e = vec[low];//采用替换代替交换
    }
    vec[low] = e;//替换回去
    return low;
}

2.3优化小数组时的排序方案

  如果数组非常小,其实快速排序反而不如直接插入排序来得更好(直接插入是简单排序中性能最好的)。

#define MAX_SORT 7  
void QSort(vector<int>& vec,int low ,int high)
{
    int pivot;
    //if (low < high)
    if ((high-low)>MAX_SORT)
    {
        pivot = Partition(vec,low,high);

        QSort(vec, low, pivot - 1);
        QSort(vec, pivot + 1, high);

    }
    else
        InsertSort(vec);
}
void InsertSort(vector<int>& vec)//直接插入排序
{
    for (int i = 1; i < vec.size(); i++)
    {
        int e,j;
        if (vec[i - 1] > vec[i])
        {
            e = vec[i];
            for (j = i - 1; j >= 0 && vec[j] > e; j--)
                vec[j + 1] = vec[j];
            vec[j + 1] = e;
        }
    }
}

2.4优化递归操作

  如果能减少递归,将会大大提高性能。

void QSort(vector<int>& vec,int low ,int high)
{
    int pivot;
    //if (low < high)
    if ((high-low)>MAX_SORT)
    {
        /*pivot = Partition(vec,low,high);

        QSort(vec, low, pivot - 1);
        QSort(vec, pivot + 1, high);*/

        /*尾递归优化*/
        while (low < high)
        {
            pivot = Partition(vec, low, high);
            QSort(vec, low, pivot - 1);
            low = pivot + 1;
        }

    }
    else
        InsertSort(vec);
}

  在VS上运行结果如下:
2

3.排序总结

排序方法 平均情况 最好情况 最坏情况 辅助空间 稳定性
冒泡排序 O ( n 2 ) O ( n ) O ( n 2 ) O ( 1 ) 稳定
简单选择排序 O ( n 2 ) O ( n 2 ) O ( n 2 ) O ( 1 ) 稳定
直接插入排序 O ( n 2 ) O ( n ) O ( n 2 ) O ( 1 ) 稳定
希尔排序 O ( n l o g n ) ~ O ( n 2 ) O ( n 2 / 3 ) O ( n 2 ) O ( 1 ) 不稳定
堆排序 O ( n l o g n ) O ( n l o g n ) O ( n l o g n ) O ( 1 ) 不稳定
归并排序 O ( n l o g n ) O ( n l o g n ) O ( n l o g n ) O ( n ) 稳定
快速排序 O ( n l o g n ) O ( n l o g n ) O ( n 2 ) O ( n l o g n ) ~ O ( n ) 不稳定

猜你喜欢

转载自blog.csdn.net/hu_weichen/article/details/80870093