2021-08-17

排序专题

今天来总结一下排序相关的各种知识,并且实现:

快速排序:

C++中可以使用std::sort()进行快速排序,但是最好还是要知道其中的原理和实现细节:
代码如下:

void quick_sort(vector<int>&nums,int l,int r){//左指针和右指针
    if(l+1>=r){
        return;
    }
    int first=l,last=r-1,key=nums[first];//first指针和last指针、key是正在检查的指针
    while(first<last){//当first还没有超过last时
    //先调整last指针的值
        while(first<last&&nums[last]>=key){//当first不超过last并且大于key时
            --last;
        }
        nums[first]=nums[last];//修改first指针指向的值
        //再调整first指针的值
        while(first<last&&nums[first]<=key){
            ++first;
        }
        nums[last]=nums[first];
    }
    nums[first]=key;
    quick_sort(nums,l,first);
    quick_sort(nums,first+1,r);
}

有一个介绍快速排序细节的文章:图解快速排序
实际上中心思想就是先递归地找到其中某一个元素的位置,使用交换的思想,当出现两个大小关系不正确的元素时,将他们进行交换。
里面说的已经相当清楚了,我们来关注时间复杂度:
最差时间复杂度与冒泡排序一致:O(N^2),平均时间复杂度是O(NlogN);

归并排序

归并排序中需要开辟一个临时数组来辅助我们的归并,也就是说比插入排序或者选择排序都要使用更多的存储空间,需要O(n)的额外空间来完成这个排序。只不过现在计算机中时间的效率要比空间的效率重要得多。无论是内存还是硬盘可以存储的数据越来越多,所以设计一个算法,时间复杂度是要优先考虑的。

归并的过程可以用下面这篇文章中的图解法得到:
归并排序图解
其中的过程也是可以使用递归的写法完成的:

void merge_sort(vector<int>&nums,int l,int r,vector<int>&temp){
    if(l+1>=r){
        return;
    }

    int m=l+(r-1)/2;//中间数
    merge_sort(nums,l,m,temp);
    merge_sort(nums,m,r,temp);
    int p=l,q=m,i=l;
    while(p>m||q<r){
        if(q>=r||(p<m&&nums[p]<=nums[q])){
            temp[i++]=nums[p++];
        }else{
            temp[i++]=nums[q++];
        }
    }
    for(i=l;i<r;++i){
        nums[i]=temp[i];
    }
}

归并排序的时间复杂度:O(NlogN);
空间复杂度:O(N);

插入排序

插入排序的思想是比较简单的,具体思路可以参考这篇文章中的动画:插入排序动画
代码如下:

void insertion_sort(vestor<int> &nums,int n){
    for(int i=0;i<n;++i){
        for(int j=i;j>0&&nums[j]<nums[j-1];--j){
            swap(nums[j],nums[j-1]);
        }
    }
}

冒泡排序

冒泡排序的整体思路是比较简单的,主要是检查相邻两个元素的大小,当大小关系与位置关系不一致时,就调整两者的位置,代码如下:

void bubble_sort(vector<int> &nums,int n){
    bool swapped;
    for(int i=1;i<n;++i){
        swapped=false;
        for(int j=1;j<n-i+1;++j){
            if(nums[j]<nums[j-1]){
                swap(nums[j],nums[j-1]);
                swapped=true;
            }
        }
        if(!swapped){
            break;
        }
    }
}

选择排序

选择排序的思想也是比较简单的,就是从未排好序的部分中选择出最小的数字放在最前面;
代码如下:

void selection_sort(vector<int>&nums,int n){
    int mid;
    for(int i=0;i<n-1;++i){
        mid=i;
        for(int j=i+1;j<n;++j){
            if(nums[j]<nums[mid]){
                mid=j;
            }
        }
        swap(nums[mid],nums[i]);
    }
}

以上各个算法的思想细节以及代码都需要牢记,时间复杂度可以参考下图:
在这里插入图片描述
以上排序算法的使用方法:

void sort(){
    vector<int> nums={1,3,5,7,2,6,4,8,9,2,8,7,6,0,3,5,9,4,1,0};
    vector<int> temp(nums.size());
    sort(nums.begin(),nums.end());
    quick_sort(nums,0,nums.size());
    merge_sort(nums,0,nums.size(),temp);
    insertion_sort(nums,nums.size());
    bubble_sort(nums,nums.size());
    selection_sort(nums,nums.size());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值