快速排序

本文介绍了快速排序的基本原理,以及如何处理逆序对和找出数组中第n大的元素。通过对比归并排序,讨论了快速排序在处理近乎有序和重复数字数组时的效率问题,并提出了优化方案,包括随机选取基准值和三路快速排序方法。
摘要由CSDN通过智能技术生成

排序过程

将数组第一个元素作为分界点,位置为l,逐渐遍历之后的元素,判断和第一个元素的大小;l代表第一个位置,那么[l+1…j]代表小于第一个值的数组,[j+1…i-1]代表大于第一个值的数组,i代表接下来要判断的位置;当i处的值大于第一个值,则直接i++判断下一个;当i的值小于第一个值,则 j++ i++判断下一个;当i等于n+1后,j的位置即是第一个值的位置。

归并排序和快速排序的衍生问题

两种算法都使用了分治算法:将大问题分为同样的小问题,小问题解决了就能解决大问题。
但两者的区别是分组的依据不同,一个是直接一分为二,一个是按照一个数值分开。

逆序对

可以用来衡量数组的有序程度。
暴力解法:考察每一个序对 O ( n 2 ) O(n^2) O(n2)
归并排序解决:在归并过程中,如果是右边的数组要小,此时左边剩下的数和这个数都是逆序对,只要再归并过程中按组的单位记录出来。

取出数组中第n大的数组

暴力解法:排序再索引 n l o g n nlog_n nlogn
快速排序解决:用第一位进行第一次快速排序,找到位置后与n进行比较,然后只需要n所在的组进行下一次快速排序,而另一部分不包含n位置的可以直接放弃。

代码

main.cpp


#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
#include "MergeSort.h"
#include "InsertionSort.h"

using namespace std;

// 对arr[l...r]部分进行partition操作,找出p值
// 函数作用:返回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; // 初始值设置为1(第一位是0),arr[l+1...j] < v ; arr[j+1...i) > v
    for( int i = l + 1 ; i <= r ; i ++ )  // i是用来考察的值,知道最后一个
        if( arr[i] < v ){
   
            j ++;
            swap( arr[j] , arr[i] ); // 交换大于的数组第一位和正在考察位置的值
        }

    swap( arr[l] , arr[j]); // l还在第一个位置,换到第j个位置上

    return j; // 返回索引值
}

// 对arr[l...r]部分进行快速排序,内部递归函数
template <typename T>
void __quickSort(T arr[], int l, int r){
    // 参数代表数组,初始,末尾 

    if( l >= r ) // 停止条件
        return;

    int p = __partition(arr, l, r);  // 返回索引值p,p将数组分为两部分
    __quickSort(arr, l, p-1 );
    __quickSort(arr, p+1, r);
}

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

    __quickSort(arr, 0, n-1);
}


int main() {
   

    int n = 1000000;

    cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
    int* arr1 = SortTestHelper::generateRandomArray(n,0,n);
    int* arr2 = SortTestHelper::copyIntArray(arr1,n);

    SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n);
    SortTestHelper::testSort("Quick Sort", quickSort, arr2, n);

    delete[] arr1;
    delete[] arr2;

    return 0;
}

MergeSort.h


#ifndef INC_05_QUICK_SORT_MERGESORT_H
#define INC_05_QUICK_SORT_MERGESORT_H

#include <iostream>
#include <algorithm>
#include "InsertionSort.h"

using namespace std;


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 ++;}
    }
}

template<typename T>
void __mergeSort(T arr[], int l, int r){
   

    if( r - l <= 15 ){
   
        insertionSort(arr, l, r);
        return;
    }

    int mid = (l+r)/2;
    __mergeSort(arr, l, mid);
    __mergeSort(arr, mid+1, r);
    if( arr[mid] > arr[mid+1] )
        __merge(arr, l, mid, r);
}

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

    __mergeSort( arr , 0 , n-1 );
}

#endif //INC_05_QUICK_SORT_MERGESORT_H

InsertionSort.h



#ifndef INC_05_QUICK_SORT_INSERTIONSORT_H
#define INC_05_QUICK_SORT_INSERTIONSORT_H

#include <iostream>
#include <algorithm>

using namespace std;


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

    for( int i = 1 ; i < n ; i ++ ) {
   

        T e = arr[i];
        int j;
        for (j = i; j > 0 && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}

// 对arr[l...r]范围的数组进行插入排序
template<typename T>
void insertionSort(T arr[], int l, int r){
   

    for( int i = l+1 ; i <= r ; i ++ ) {
   

        T e = arr[i];
        int j;
        for (j = i; j > l && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}

#endif //INC_05_QUICK_SORT_INSERTIONSORT_H

SortTestHelper.h

#ifndef INC_05_QUICK_SORT_ANOTHER_PARTITION_SORTTESTHELPER_H
#define INC_05_QUICK_SORT_ANOTHER_PARTITION_SORTTESTHELPER_H

#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cassert>

using namespace std;


namespace SortTestHelper {
   

    int *generateRandomArray(int n, int range_l, int range_r) {
   

        int *arr = new int[n];

        srand(time(NULL));
        for (int i = 0; i < n; i++)
            arr[i] = rand() % (range_r - range_l + 1) + range_l;
        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;
    }

    int *copyIntArray(int a[], int n){
   

        int *arr = new int[n];
        copy(a, a+n, arr);
        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>
    void printArray(T arr[], int l, int r) {
   

        for (int i = l; i <= r; 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 testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值