排序算法---快速排序

快速排序

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为2个子序列,然后递归地排序两个子序列。

快速排序是一个不稳定的算法,在经过排序之后,可能会对相同值的元素的相对位置造成改变。

快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

快速排序只是使用数组原本的空间进行排序,所以所占用的空间应该是常量级的,但是由于每次划分之后是递归调用,所以递归调用在运行的过程中会消耗一定的空间,在一般情况下的空间复杂度为 O(logn),在最差的情况下,若每次只完成了一个元素,那么空间复杂度为 O(n)。所以我们一般认为快速排序的空间复杂度为 O(logn)

方法一:遍历交换法。

取一个key元素,我一般取数组的最后一个元素。定义一个指针index从头向后遍历,再定义一个指针位pre于第一个元素之前。如果index元素比key小,pre向前移动一位,交换index和key的元素,把小的放前、大的放后。index遍历到最后,将pre+1和key进行交换,这样比key小的都在它前面,比key大的都在它后面了。再继续对左右两边进行递归运算。

#include<iostream>
#include<vector>

using namespace std;

void Swap(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}
 
// int Partition(int data[], int start, int end){
int Partition(vector<int>& data, int start, int end){
    cout << start << " " << end << endl;
    int pre = start-1;
 
    for(int index = start; index < end; ++index){
        if(data[index] < data[end]){
            ++pre;
            if(pre != index){
                Swap(data[index], data[pre]);
            }
        }
    }
    ++pre;
    Swap(data[pre], data[end]);
     
    return pre ;
}
 
// void QuickSort(int data[], int start, int end){
void QuickSort(vector<int>& data, int start, int end){
    if(start < end){
        int index = Partition(data, start, end);
        if(index > start){
            QuickSort(data, start, index-1);
        }
        if(index < end){
            QuickSort(data, index+1, end);
        }
    }
}
int main(){
 
    int a[7] = {5,3,2,8,1,4,9};
    vector<int> input(a, a+7);
    int size = input.size();
 
    cout << "before:";
    for(int i=0; i<size; ++i){
        cout <<input[i] << " "; 
    }
    cout << endl;
 
    QuickSort(input, 0, 6);
 
 
    cout << "after :";
    for(int i=0; i<size; ++i){
        cout << input[i] << " "; 
    }
    cout << endl;
    return 0;
}

方法二:填坑法

取一个p,我们取第一个元素。将start作为一个坑位,从后向前找,比p大的end拿过来放在坑里,同时end作为一个坑位。再从前向后找,比p小的start拿过来放在坑里,同时start作为一个坑位,直到start=end,将p放在最后的位置。这样比p小的都在它的左边,比p大的都在它的右边,再继续对左右两侧进行递归。

int partition(int a[], int start, int end){
    int p = a[start];
    while(start < end){
        while(a[end] >= p && start < end) end--;
        a[start] = a[end];
        while(a[start] < p && start < end) start++;
        a[end] = a[start];
    }
    a[start] = p;
    return start;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值