【数据结构 C++】排序——冒泡、插入、选择、希尔、归并、快排、堆排序

LeetCode 912. 排序数组
给你一个整数数组 nums,请你将该数组升序排列。

示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

提示:
1 <= nums.length <= 50000
-50000 <= nums[i] <= 50000

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        //bubbleSort(nums);
        
        //selectionSort(nums);
        
        //InsertionSort(nums);
        
        //ShellSort(nums);
        
        //return mergeSort(nums);
        
        //quickSort(nums,0,nums.size()-1);

        heapSort(nums);
        
        return nums;
    }

    // 冒泡排序 O(n²)
    void bubbleSort(vector<int>& nums){
        for(int i=nums.size()-1;i>0;i--)
            for(int j=0;j<i;j++){
                if(nums[j]>nums[j+1])
                    swap(nums[j],nums[j+1]);
            }
    }

    // 选择排序 O(n²)
    void selectionSort(vector<int>& nums){
        for(int i=nums.size()-1;i>0;i--){
            int maxSub=0;
            for(int j=1;j<=i;j++){
                if(nums[j]>nums[maxSub])
                    maxSub=j;
            }
            swap(nums[i],nums[maxSub]);
        }
            
    }

    // 插入排序 O(n²)
    void InsertionSort(vector<int>& nums){
        for(int i=1;i<nums.size();i++){
            int pos=i;
            int curVal = nums[i];
            while(pos>0 && nums[pos-1]>curVal){
                nums[pos]=nums[pos-1];
                pos--;
            }
            nums[pos]=curVal;     
        }
    }

    //希尔排序 O(nlogn) 
    void ShellSort(vector<int>& nums){      
        for(int gap = nums.size()/2; gap>0; gap/=2)
            for(int i=gap; i<nums.size();i++){
                int curVal = nums[i];
                int pos=i;
                while(pos>=gap && nums[pos-gap]>curVal){
                    nums[pos]=nums[pos-gap];
                    pos-=gap;
                }
                nums[pos]=curVal;
            }
    }
	
    // 归并排序 O(nlogn)  空间上的开销
    vector<int> mergeSort(vector<int> nums){  
        if(nums.size()<2)
            return nums;

        int l=0,r=nums.size()-1;
        int mid=(l+r)/2;
        vector<int> left = mergeSort(vector<int>(nums.begin(),nums.begin()+mid+1)); //类似数组切片 ,注意mid+1
        vector<int> right= mergeSort(vector<int>(nums.begin()+mid+1,nums.end()));

        int i=0,j=0;
        vector<int> res;
        while(i<left.size() && j<right.size()){
            if(left[i]<right[j]){
                res.push_back(left[i]);
                i++;
            }
            else{
                res.push_back(right[j]);
                j++;
            }          
        }

        if(i<left.size())
            res.insert(res.end(),left.begin()+i,left.end());
        else if(j<right.size())
            res.insert(res.end(),right.begin()+j,right.end()); 
        return res; 
    } 
	
    //归并排序 写法2 temp数组有效利用空间
    void mergeSort(vector<int>& nums, vector<int>& temp, int l, int r){
        if(r-l<1) return;

        int mid=(l+r)/2;
        mergeSort(nums,temp,l,mid);
        mergeSort(nums,temp,mid+1,r);
        
        int i=l,k=l,j=mid+1;
        while(i<=mid && j<=r)
            if(nums[i]<=nums[j]) temp[k++]=nums[i++];
            else temp[k++]=nums[j++];

        while(i<=mid) temp[k++]=nums[i++];
        while(j<=r) temp[k++]=nums[j++];
        while(--j>=l) nums[j]=temp[j];
    }
	
    // 快速排序 O(nlogn)  
    void quickSort(vector<int>& nums, int l,int r){
        if(l>=r)
            return;
			
        swap(nums[l], nums[rand() % (r - l + 1) + l]); // 不随机会超时
        int pivot=nums[l];
        int i=l+1, j=r; //注意此处从 l+1 开始算
        while(i<=j){	//注意比较符号 <=
            while(i<=j && nums[i]<=pivot) i++;
            while(i<=j && nums[j]>=pivot)j--;
            if(j<i) break;
            swap(nums[i],nums[j]);
         }
         swap(nums[j],nums[l]);
         quickSort(nums,l,j-1);
         quickSort(nums,j+1,r);

      }
    
	//快速排序  写法2
    void quickSort2(vector<int>& nums,int l, int r){
        if(l>=r) return;

        //swap(nums[l],nums[random()%(r-l+1)+l]);
        int pivot=nums[l];
        int i=l,j=r;
        while(i<j){
            while(i<j && nums[j]>=pivot)j--;
            while(i<j && nums[i]<=pivot)i++;
            swap(nums[i],nums[j]);
        }
        swap(nums[l],nums[i]);
        quickSort2(nums,l,i-1);
        quickSort2(nums,i+1,r);
    }
      // 堆排序 O(nlogn) 
      void heapSort(vector<int>& nums){
        int len=nums.size();
        for(int i=len/2-1; i>=0;i-- ) //构建大根堆
            MaxHeapify(nums, len, i);

        for(int i=len-1;i>0;i--){
            swap(nums[0],nums[i]); // 根(最大值)放在末尾排序部分
            MaxHeapify(nums,i, 0); // 调整未排序部分
        }
      }

      //堆调整 
      void MaxHeapify(vector<int>& nums,int len,int index){
        int lc=2*index+1;
        int rc=2*index+2;
        int largest=index;

        if(lc<len && nums[lc]>nums[largest])
            largest=lc;
        if(rc<len && nums[rc]>nums[largest])
            largest=rc;

        if(largest!=index){
            swap(nums[index],nums[largest]); //交换父子节点的值
            MaxHeapify(nums, len, largest); //调整子树
        }
      }
    
};
posted @ 2021-07-22 20:53  砥才人  阅读(405)  评论(0编辑  收藏  举报