数据结构与算法C++之快速排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majinlei121/article/details/83896128

快速排序是一种比归并排序还要快的排序算法,具体原理如下图所示
在这里插入图片描述
对上图所示的数组,首先随机选取一个参照元素,一般选取最左边的元素4为参照元素,然后将数组排序成以4为分界点,左边都是小于4的元素,右边都是大于4的元素,按照这种方式进行不断递归,就可实现整个数组的排序。
在这里插入图片描述
上图显示的是程序的实现过程,首先指定最左边的元素 v v 为参照元素,索引为 l l ,小于元素 v v 的 最后一个元素的索引为 j j ,正在处理的元素在大于元素 v v 的元素的后面,索引为 i i ,如果 a r r [ i ] > v arr[i] > v ,此时就将元素 i i 合并到左边的元素中, i + + i++ ,如果此时 a r r [ i ] < v arr[i] < v ,那么就将 i i 位置的元素与 j + 1 j+1 位置的元素交换,交换后 j + + j++ ,此时 j j 位置的元素就是小于 v v 的,原来 j j 位置的大于 v v 元素交换到 i i 位置了, i + + i++ ,以此类推, i i 遍历到数组的最后一个元素后for循环停止。此时还需要最后将 l l 位置的元素与 j j 位置的元素交换,完成partition操作。
首先对整个数组进行partition操作,然后通过递归过程,最终将只处理一个只有一个元素的数组,一个元素的数组是有序的,然后就可对整个数组进行排序。
关于快速排序的原理,也可参考这两篇博客,博客一博客二
下面是程序实现

#include <iostream>

#ifndef _SORTINGHELP_H_
#define _SORTINGHELP_H_
#include "SortingHelp.h"
#endif // _SORTINGHELP_H_

#include "MergeSorting.h"

using namespace std;

//对arr[l...r]进行partition操作
//返回p,使得arr[l...p-1] < arr[p]; arr[p+1...r] > arr[p]
template<typename T>
int __partition(T arr[], int l, int r){

    T v = arr[l];
    int j = l;
    //arr[l+1...j] < v; arr[j+1...i) > v
    for(int i = l + 1; i <= r; i++){
        if (arr[i] < v){
            swap(arr[i], arr[j + 1]);
            j++;
        }
    }
    swap(arr[l], arr[j]);
    return j;
}

//对arr[l...r]部分进行排序
template<typename T>
void __quickSorting(T arr[], int l, int r){
    if (l >= r)
        return;

    int p = __partition(arr, l, r);
    __quickSorting(arr, l, p - 1);
    __quickSorting(arr, p + 1, r);

}


template<typename T>
void quickSorting(T arr[], int n){

    __quickSorting(arr, 0, n-1);

}

int main(){
    int a[] = {8,7,6,5,4,3,2,1};
    int n = 8;
    quickSorting(a, n);
    for(int i = 0; i < n; i++){
        cout<<a[i]<<" ";
    }
    cout<<endl;
    return 0;
}

//int main()
//{
//    int n = 100000;
//    int *arr = generateRandomArray(n, 0, n);
//    int *arr2 = copyIntArray(arr, n);
//    testSorting("MergeSorting", MergeSorting, arr, n);
//    testSorting("quickSorting", quickSorting, arr2, n);
//    delete[] arr;//最后删除数组开辟的空间
//    delete[] arr2;
//    return 0;
//}

输出结果为
在这里插入图片描述
与归并排序比较

int main()
{
    int n = 100000;
    int *arr = generateRandomArray(n, 0, n);
    int *arr2 = copyIntArray(arr, n);
    testSorting("MergeSorting", MergeSorting, arr, n);
    testSorting("quickSorting", quickSorting, arr2, n);
    delete[] arr;//最后删除数组开辟的空间
    delete[] arr2;
    return 0;
}

输出为
在这里插入图片描述
排序10万个元素的数组,快速排序要快于归并排序
上面程序中引用的 SortingHelp.h 和 MergeSorting.h 如下,
关于归并排序请参见以前博客数据结构与算法C++之归并排序

//MergeSorting.h

#include <iostream>

#ifndef _SORTINGHELP_H_
#define _SORTINGHELP_H_
#include "SortingHelp.h"
#endif // _SORTINGHELP_H_

using namespace std;

//将arr[l...mid]和arr[mid+1...r]两部分进行归并
template<typename T>
void __merge(T arr[], int l, int mid, int r){
    T aux[r-l+1];
    for (int i = l; i <= r; i++){
        aux[i-l] = arr[i];
    }

    int i = l, j = mid + 1;
    for (int k = l; k <= r; k++){
        if (i > mid){
            arr[k] = aux[j-l];
            j++;
        }
        else if (j > r){
            arr[k] = aux[i-l];
            i++;
        }

        else if (aux[i-l] < aux[j-l]){
            arr[k] = aux[i-l];
            i++;
        }
        else{
            arr[k] = aux[j-l];
            j++;
        }
    }
}

//递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void __mergeSorting(T arr[], int l, int r){
    if (l >= r)
        return;

    int mid = (l + r)/2;
    __mergeSorting(arr, l, mid);
    __mergeSorting(arr, mid+1, r);
    if (arr[mid] > arr[mid+1])//如果左边的序列已经小于右边的序列,就不用合并了
        __merge(arr, l, mid, r);

}

template<typename T>
void MergeSorting(T arr[], int n){

    __mergeSorting(arr, 0, n-1);

}
//SortingHelp.h

#include <iostream>
#include <ctime>  //time()函数
#include <cstdlib> //rand()函数
#include <cassert> //assert()函数


using namespace std;

int* generateRandomArray(int n, int rangeL, int rangeR){//生成随机数组
    assert(rangeL < rangeR);
    int *arr = new int[n];
    srand(time(NULL));
    for (int i = 0; i < n; i++){
        arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
    }
    return arr;
}

int* generateNearlyOrderedArray(int n, int swapTimes){//生成近乎有序的数组
    int *arr = new int[n];
    for (int i = 0; i < n; i++){
        arr[i] = i;
    }
    srand(time(NULL));
    for (int i = 0; i < swapTimes; i++){
        int posx = rand() % n;
        int posy = rand() % n;
        swap(arr[posx], arr[posy]);
    }
    return arr;
}


template<typename T>
void printArray(T arr[], int n){//打印数组元素
    for (int i = 0; i < n; i ++){
        cout<<arr[i]<<" ";
    }
    cout<<endl; //换行
    return;
}


template<typename T>
bool isSorted(T arr[], int n){//测试排序算法是否正确
    for (int i = 0; i < n - 1; i++){
        if (arr[i] > arr[i + 1])
            return false;
    }
    return true;
}

template<typename T>
void testSorting(string sortName, void(*sorting)(T[], int), T arr[], int n){
//第二个参数是传入排序函数的指针

    clock_t startClock = clock();
    sorting(arr, n);
    clock_t endClock = clock();
    assert(isSorted(arr, n));
    cout<<sortName<<" : "<<double(endClock-startClock)/CLOCKS_PER_SEC<<" s"<<endl;
    return;
}

int* copyIntArray(int arr[], int n){
    int* arr2 = new int[n];
    copy(arr, arr+n, arr2);
    return arr2;
}

template<typename T> //定义模板类型,使对各种数据类型都适用,如double,float,string
void SelectionSorting(T a[], int n){//选择排序算法
    for (int i = 0; i < n; i++){
        int minIndex = i;
        for (int j = i + 1; j < n; j++){
            if (a[j] < a[minIndex])
                minIndex = j;
        }
        swap(a[i], a[minIndex]);
    }
}

template<typename T>
void InsertionSortingImproved(T arr[], int n){
    for (int i = 0; i < n - 1; i++){
        T temp = arr[i+1];
        int j;
        for (j = i + 1; j > 0; j--){
            if (arr[j-1] > temp){
                arr[j] = arr[j-1];
            }
            else{
                break;
            }
        }
        arr[j] = temp;
    }
    return;
}

猜你喜欢

转载自blog.csdn.net/majinlei121/article/details/83896128