快速排序

概述

快速排序和归并排序一样也是分而治之策略的应用,基本思路是在数组中选取一个主元,以它为标准,遍历数组把小于它的数放在右边,大于它的数放在左边。递归上述过程直至有序。


选主元

选主元与划分子集这两个问题关乎快速排序的效率问题。选主元有很多方式,比如直接那第一个数作主元,那么当数组基本有序时那么时间复杂度就变成了O(n^2)了,而不是O(nlogn),也可以利用随机函数来选取下标,从而确定主元,但是rand()函数却是O(n^2)的时间复杂度。比较好的做法是选取数组头、中、尾的中位数作主元。算法如下:

int Median3(int* data ,int left , int right)
{
    //这里swap函数是利用c++的引用方法 
    int mid = (left+right)/2;
    if(data[left]>data[mid]){
        Swap(data[left],data[mid]);
    }
    if(data[left]>data[right]){
        Swap(data[left],data[right]);
    }
    if(data[mid]>data[right]){
        Swap(data[mid],data[right]);
    }
    //这个时候已经满足
    //data[left]<=data[mid]<=data[right] 
    return data[mid];
}

子集划分

主要思想:构造前后两个指针low = 0,high = size-1,分别找到左边第一个大于主元的数,右边第一个小于主元的数,如果low

void QuickSort(int* data ,int left,int right)
{
    if(left >= right){
        return;
    }
    int pivot = Median3(data,left,right);
    int low,high;
    low = left;
    high = right;
    //将序列中比基准小的移到基准左边,大的移到右边
    //以下是子集划分 
    while(1){
        //找到左边第一个大于主元的数 
        while(data[++low] < pivot );
        //找到邮编第一个小于主元的数 
        while(data[--high] > pivot);
        if(low < high){
            Swap(&data[low],&data[high]);   
        }else{
            break;  
        }
    }
    QuickSort(data,left,low-1);//递归快速排序左半部分 
    QuickSort(data,low+1,right);//递归快速排序右半部分 
}

全部代码

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

//初始化数组 
void SetArray(int* data,int size)
{
    //srand(time(0));
    cout<<"随机初始化"<<size<<"个数"<<endl;
    for(int i = 0 ; i < size ; i++){
        data[i] =rand()%100+1;
    }
}

void Print(int* data ,int size)
{
    for(int i = 0 ; i < size ; i++){
        cout<<data[i]<<" "; 
    }
    cout<<endl;
}

void Swap(int* a ,int* b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int Median3(int* data ,int left , int right)
{
    //这里swap函数是利用c++的引用方法 
    int mid = (left+right)/2;
    if(data[left]>data[mid]){
        Swap(&data[left],&data[mid]);
    }
    if(data[left]>data[right]){
        Swap(&data[left],&data[right]);
    }
    if(data[mid]>data[right]){
        Swap(&data[mid],&data[right]);
    }
    //这个时候已经满足
    //data[left]<=data[mid]<=data[right]
    return data[mid];
}

void QuickSort(int* data ,int left,int right)
{
    if(left >= right){
        return;
    }
    int pivot = Median3(data,left,right);
    int low,high;
    low = left;
    high = right;
    //将序列中比基准小的移到基准左边,大的移到右边
    //以下是子集划分 
    while(1){
        //找到左边第一个大于主元的数 
        while(data[++low] < pivot );
        //找到邮编第一个小于主元的数 
        while(data[--high] > pivot);
        if(low < high){
            Swap(&data[low],&data[high]);   
        }else{
            break;  
        }
    }
    QuickSort(data,left,low-1);//递归快速排序左半部分 
    QuickSort(data,low+1,right);//递归快速排序右半部分 
}

//快速排序 
void Quick_Sort(int* data ,int size)
{
    QuickSort(data,0,size-1);
}

int main()
{
    cout<<"请输入数组长度:"<<endl;
    int size,*data;
    cin>>size; 
    data = new int[size];

    SetArray(data,size);
    cout<<"快速排序前:"<<endl;
    Print(data,size);
    cout<<"快速排序后:"<<endl;
    Quick_Sort(data,size);
    Print(data,size);

    SetArray(data,size);
    cout<<"前:"<<endl;
    Print(data,size);
    cout<<"后:"<<endl;
    Move(data,size);
    Print(data,size);

    cout<<"请输入一个数:"<<endl;
    int k;
    cin>>k; 
    SetArray(data,size);
    Print(data,size);
    cout<<"数组中第"<<k<<"小的数为:"<<endl;
    cout<<FindKth(data,0,size-1,k-1); 

    SetArray(data,size);
    Print(data,size);
    cout<<FindMax(data,size); 

    return 0;
 } 

截图:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daipuweiai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值