常用排序算法(快速排序、選擇排序、直接插入排序)

對數組進行排序

Given an array of integers nums, sort the array in ascending order.

Example 1:

Input: nums = [5,2,3,1]
Output: [1,2,3,5]
Example 2:

Input: nums = [5,1,1,2,0,0]
Output: [0,0,1,1,2,5]

在leetcode上練習了一些與數組相關的題目,之前用到排序的時候都是直接調用STL中的算法,這次自己實現一下排序的算法。分別使用:快速排序(代碼簡潔)、簡單選擇排序(代碼簡短)、直接插入排序、堆排序。

題意:此題可以使用多種排序算法進行解答,算是數據結構中的基礎題目。
方法:分別嘗試使用簡單選擇排序、直接插入排序、快速排序方法來解決,但是由於簡單選擇排序和直接插入排序的時間複雜度比較高,沒有通過所有的測試用例。

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        
        // selectSort(nums);
        // insertSort(nums);
        // quickSort(nums,0,nums.size()-1);
        // bubbleSort(nums);
        heapSort(nums);
        return nums;
        
    }

    // 簡單選擇排序
    void selectSort(vector<int>& nums){
        // 1.使用選擇排序,由於時間複雜度爲N方,測試用例通過率爲9/10.
        
        int i,j;
        int selected,temp;
        for(i=0;i<nums.size()-1;i++){
            selected = nums[i];
            for(j=i;j<nums.size();j++){
                if(selected>nums[j]){
                    temp = selected;
                    selected = nums[j];
                    nums[j] = temp;
                }
            }
            nums[i] = selected;
        }
    }

    // 直接插入排序
    void insertSort(vector<int>& nums){
        // 2.使用直接插入排序,也是由於時間複雜度爲N方,測試用例通過了9/10
        int i,j,k;
        int temp;
        for(i=1;i<nums.size();i++){
            for(j=i-1;j>=0;j--){    // 爲元素a[i],在前面找到合適的插人位置(j的後面)
                if(nums[j]<nums[i]){
                    break;
                }
            }
            if(j != i-1){
                // 將比a[i]大的數向後移
                temp = nums[i];
                for(k=i-1;k>j;k--){  
                    nums[k+1] = nums[k];
                }
                nums[j+1] = temp;   //將a[i]放到j的後面。
            }
            
        }
    }

    // 快速排序
    void quickSort(vector<int>& nums,int l,int h){
            if(l < h){
                int pivot = nums[l];
                int i = l,j = h;
                while(i < j){
                	// 從後向前找比pivot小的數。
                    while(i<j && nums[j]>pivot){
                        j--;
                    }
                    if(i<j)	
                        nums[i++] = nums[j]; 
                    // 從前往後找比pivot大的數。
                    while(i<j && nums[i]<pivot){
                        i++;
                    }
                    if(i<j)
                        nums[j--] = nums[i];
                }
                // 最後將pivot的值放到分割點上
                nums[i] = pivot;
                // 分治遞歸排序
                quickSort(nums,l,i-1);
                quickSort(nums,j+1,h);
            }
        }

    // 冒泡排序
    void bubbleSort(vector<int>& nums){
        // 時間複雜度同樣爲N方,只有9/10的用例通過
        for(int i=0;i<nums.size()-1;i++){   // 比較的趟數
            for(int j=0;j<nums.size()-i-1;j++){ // 每一趟中比較的次數
                if(nums[j]>nums[j+1]){
                    int temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
        }
    }

    // 堆排序
    void heapSort(vector<int>& nums){
        // 時間複雜度與快速排序相同,測試用例都可以通過
        int len = nums.size();
        heapBuild(nums,len);
        for(int newLen=len-1;newLen>0;newLen--){   
            swap(nums,newLen,0);
            // heapBuild(nums,newLen);
            heapAdjust(nums,0,newLen);
        }
    }
    // 建立大頂堆
    void heapBuild(vector<int>& nums,int len){
        for(int i=len/2-1;i>=0;i--){    // 從最後一個非葉結點開始調整
            heapAdjust(nums,i,len);
        }
    }
    // 調整大頂堆
    void heapAdjust(vector<int>& nums,int i,int end){
        int ded = i;
        int son = 2*i + 1;
        int largest = ded;
        if(son < end && nums[largest] < nums[son])
            largest = son;
        if(son+1 < end && nums[largest] < nums[son+1])
            largest = son + 1;
        if(largest != i){
            swap(nums,largest,i);
            heapAdjust(nums,largest,end);
        }
    }
    // 交換兩個位置上的值
    void swap(vector<int>& nums,int i,int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
};

關於堆排序:其思想是使用數據結構中的堆來實現。
算法描述描述 :

  1. 將待排序的關鍵字序列{R1,R2,R3,…Rn}構建爲一個大頂堆,此時R1爲最大值。
  2. 將R1與最後一個元素交換位置,{R1,R2,R3…Rn-1}是一個無序序列,此時{R1,R2,R3…Rn-1} \leq{Rn}
  3. 這個時候R1違反了大頂堆的定義,要對R1進行調整,讓{R1,R2,R3…Rn-1}構成大頂堆,將R1與Rn-1交換位置,此時無序序列{R1,R2,R3…Rn-2}\leq有序序列{Rn-1,Rn}
  4. 重複此過程,當有序序列中有n-1個元素時,排序完成。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章