c++ 排序算法

冒泡排序

基础版,本来想着加flag减少多余的计算,但是我这样做好像已经自动将多余的运算避免了。
写了后面的排序算法,发现我这样写思路就跟插入排序很像了。。百度后发现冒泡排序的取值应当是从nums.size() 到1 ,所以下面完全是不伦不类的插入排序。

    void swap(vector<int>& nums,int x,int y){
        int temp=nums[x];
        nums[x]=nums[y];
        nums[y]=temp;
    }
    void bubble(vector<int>& nums){
        for(int j=1;j<nums.size();j++){
            for(int i=j;i>0 and nums[i-1]>nums[i];i--){
                swap(nums,i-1,i);
            }  
        }
    }

正宗的冒泡排序是通过相邻两两比较将较大的数一步步浮出

    void bubble(vector<int>& nums){
    	bool flag=true;//添加一个变量监督剩下的排序已排好,不必要继续排序
        for(int j=nums.size();j>0 and flag==true;j--){
            flag=false;
            for(int i=1;i<j;i++){
                if(nums[i-1]>nums[i])
                    swap(nums,i-1,i);
                    flag=true;
            }  
        }
    }

选择排序

每次交换当前与最小的

    void select(vector<int>& nums){
        for(int i=0;i<nums.size()-1;i++){
            int temp=i;
            for(int j=i;j<nums.size();j++){
                if(nums[j]<nums[temp])
                    temp=j; 
            }
            swap(nums,i,temp);  
        }
    }

插入排序

将当前值插入之前合适的位置

    void insert(vector<int>& nums){
        int j,temp;
        for(int i=1;i<nums.size();i++){
            temp=nums[i];
            j=i;
            while(j>0 and nums[j-1]>temp){
                nums[j]=nums[j-1];
                j--;
            }
            nums[j]=temp;
        }
    }

希尔排序

是一个分组插入的方法,插入排序的改进版。特点不稳定,与取的增量序列gap的取值相关性很大。
等于是每隔gap个数分出一个数列执行一次插入排序,一个分出gap个小数列插入排序后,做到整体有序再整体插入排序

    void shell(vector<int>& nums){
        int j,temp;
        int gap=nums.size()/3;
        while(gap>=1){
            for(int i=gap;i<=nums.size()-gap;i++){
                temp=nums[i];
                j=i;
                while(j>=gap and nums[j-gap]>temp){
                    nums[j]=nums[j-gap];
                    j-=gap;
                }  
                nums[j]=temp;
            } 
            gap/=2;
        }

    }

堆排序

堆近似完全二叉树,分为大顶堆(每个结点的值都大于左右子结点的值),小顶堆(每个结点的值都小于左右子结点的值)。
由于使用的vector,所以下标麻烦了些。堆排序的下标需要从 1 开始
堆排序思路是按大顶堆的思路,每次找到最大值,将最大值与末尾元素swap,再忽略最后一个元素将剩下的重新调整为大顶堆。

class Solution {
public:
    void main(vector<int>& nums) {
        heap(nums);
        for(int i=0;i<nums.size();i++) cout<<nums[i]<<' ';
    }
    void heap(vector<int>& nums){
        int size=nums.size();
        int temp;
        for(int i=size/2;i>=0;i--)//将原始序列构成大顶堆
            heapadjust(nums,i,size);
        for(int i=size-1 ;i>1;i--){
            temp=nums[0];
            nums[0]=nums[i];
            nums[i]=temp;//将最大值与末尾元素调换位置,剩下的重新构成大顶堆
            
            heapadjust(nums,0,i);
        }   
    }
    void heapadjust(vector<int>& nums,int s,int length){
        int temp=nums[s];
        int x=s+1;
        for(int i=2*x;i<length;i*=2){
            if(nums[i-1]<nums[i])
                i+=1;
            if(temp>=nums[i-1])
                break;
            nums[x-1]=nums[i-1];
            x=i;
        }
        nums[x-1]=temp;
    }
};

快速排序

基本方法

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        Qsort(nums,0,nums.size()-1);
        for(int i=0;i<nums.size();i++) cout<<nums[i]<<' ';
        return 0;
    }
    void swap(vector<int>& nums,int x,int y){
        int temp=nums[x];
        nums[x]=nums[y];
        nums[y]=temp;
    }
    void Qsort(vector<int>& nums, int begin, int end){
        int pivot;
        if(begin<end){
            pivot=partition(nums,begin,end); //找中间值,将nums小的左边,大的右边
            Qsort(nums,begin,pivot-1);
            Qsort(nums,pivot+1,end);
        }
    }
    int partition(vector<int>& nums,int low,int high){
        int pivotkey=nums[low];
        int temp;
        while(low<high){
            while(low<high && nums[high]>=pivotkey) high--;
            swap(nums,low,high);
            while(low<high && nums[low]<=pivotkey) low++;
            swap(nums,low,high);
        }   
        return low;
    }
};

优化了选择pivot,和减少了不必要的交换。

class Solution {
public:
    void main(vector<int>& nums) {
        Qsort(nums,0,nums.size()-1);
        for(int i=0;i<nums.size();i++) cout<<nums[i]<<' ';
    }
    void swap(vector<int>& nums,int x,int y){
        int temp=nums[x];
        nums[x]=nums[y];
        nums[y]=temp;
    }
    
    void Qsort(vector<int>& nums, int begin, int end){
        int pivot;
        if(begin<end){
            pivot=partition(nums,begin,end); //找中间值,将nums小的左边,大的右边
            Qsort(nums,begin,pivot-1);
            Qsort(nums,pivot+1,end);
        }
    }
    int partition(vector<int>& nums,int low,int high){
        int pivotkey;
        int middle=low+(high-low)/2;
        if(nums[middle]>nums[high]) swap(nums,middle,high);
        if(nums[low]>nums[high]) swap(nums,low,high);
        if(nums[low]<nums[middle]) swap(nums,middle,low);
        pivotkey=nums[low];//中值换到low的位置上
        while(low<high){
            while(low<high && nums[high]>=pivotkey) high--;
            nums[low]=nums[high];//减少不必要的交换,改为闭合赋值;

            while(low<high && nums[low]<=pivotkey) low++;
            nums[high]=nums[low];
        }   
        nums[low]=pivotkey;
        return low;
    }
};

归并排序

递归实现

class Solution {
public:
    void main(vector<int>& nums) {
        Merging(nums,0,nums.size()-1);
        for(int i=0;i<nums.size();i++) cout<<nums[i]<<' ';
    }
    
    void Merging(vector<int>& nums,int x,int y){
        int mid=(x+y)/2;
        if(x<y){
            Merging(nums,x,mid);
            Merging(nums,mid+1,y);
            Mergsort(nums,x,mid,y);
        }
    }
    void Mergsort(vector<int>& nums,int x,int m,int y){
        cout<<x<<' ';
        cout<<m<<' ';
        cout<<y<<endl;
        const int N=204800;
        int n1=m-x+1,n2=y-m;
        vector<int> left(n1+1),right(n2+1);
        for(int i=0;i<n1;i++) left[i]=nums[x+i];
        left[n1]=N;
        for(int j=0;j<n2;j++) right[j]=nums[m+1+j];    
        right[n2]=N;
        int i=0,j=0;
        for(int k=x;k<y+1;k++){
            if(left[i]<right[j]){
                nums[k]=left[i];
                i++;
            }
            else{
                nums[k]=right[j];
                j++;
            }

        }
    }
};

桶排序

这是简单版的桶排序代码,正式版本的思路应该是

  1. 将待排序元素划分到不同的桶。先扫描一遍序列求出最大值 maxV 和最小值 minV ,设桶的个数为 k ,则把区间 [minV, maxV] 均匀划分成 k 个区间,每个区间就是一个桶。将序列中的元素分配到各自的桶。
  2. 对每个桶内的元素进行排序。可以选择任意一种排序算法。
  3. 将各个桶中的元素合并成一个大的有序序列。
  4. 假设数据是均匀分布的,则每个桶的元素平均个数为 n/k 。假设选择用快速排序对每个桶内的元素进行排序,那么每次排序的时间复杂度为 O(n/klog(n/k)) 。总的时间复杂度为 O(n)+O(m)O(n/klog(n/k)) = O(n+nlog(n/k)) = O(n+nlogn-nlogk 。当 k 接近于 n 时,桶排序的时间复杂度就可以金斯认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,空间就越大。
计数排序与基数排序都是桶排序的一种。
    void bucket(vector<int>& nums){
        //查找最大最小值
        int max=0,min=204800;
        for(int i=0;i<nums.size();i++){
            if(nums[i]>max) max=nums[i];
            if(nums[i]<min) min=nums[i];
        }
        //创建桶并计数
        vector<int> temp(max+1,0);
        for(int i=0;i<nums.size();i++){
            temp[nums[i]]++;
        }
        for(int i=0;i<temp.size();i++) cout<<temp[i]<<' ';
        //将数字按桶放回
        int j=0;
        for(int i=min;i<=max;i++){
            while(temp[i]-->0){
                cout<<temp[i]<<' '<<i<<' '<<j<<endl;
                nums[j++]=i;
            }     
        }
        
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值