不定類型長度的排序系統【+各類排序算法詳解】(C++實現)


創作不易,如果以下內容對你有幫助,別忘了點一個贊,讓更多的小夥伴能看到吧~~


排序算法詳情

一 、冒泡排序

  • 原理

    冒泡排序算法的基本原理就是比較相鄰兩個數字的大小。將兩個數中比較大的那個數交換到靠後的位置,不斷交換下去就可以將最大的那兩個數放到隊列的尾部。然後重頭再次交換)(交換list.lenght-1次),直到將數列排成有序數列。

  • 時間複雜度(平均): O(n^2)

  • 時間複雜度(最壞): O(n^2)

  • 時間複雜度(最好): O(n)

  • 空間複雜度: O(1)

  • 穩定性: 穩定

  • 代碼實現

    /*
    函數功能: 冒泡排序
    函數名稱: bubbleSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    template<typename T>
    void bubbleSort(T *arr, int len)
    {
        T temp;
        if(len <= 1)
            return;
        for(int i=0;i<len-1;i++)
        {
            for(int j=0;j<len-i-1;j++)
            {
                if(arr[j]>arr[j+1])
                {
                    swap(arr,j, j+1);
                }
            }
        }
    }
    

二、插入排序

  • 原理:

    插入排序首先將數列分爲兩部分,數列的第一數爲left,其餘數位right部分。然後將right部分中的數逐一取出,插入到left部分的適當位置。當right部分爲空時,left部分就成了一個有序的序列。

  • 時間複雜度(平均): O(n^2)
  • 時間複雜度(最壞): O(n^2)
  • 時間複雜度(最好): O(n)
  • 空間複雜度: O(1)
  • 穩定性: 穩定
  • 代碼實現:
    /*
    函數功能: 插入排序
    函數名稱: insertSort
    參數: arr -- 傳入數組指針
         len -- 數組長度
    返回值: void
    */
    template<typename T>
    void insertSort(T *arr, int len)
    {
        T temp;
        int j;
        if(len <= 1)
            return;
        for(int i=1; i<len;i++)
        {
            j = i;
            while(j>0)
            {
                if(arr[j] < arr[j-1])
                {
                    swap(arr, j, j-1);
                    j--;
                }else{
                    break;
                }
            }
        }
    }
    

三、選擇排序

  • 原理:

    選擇排序從數列中選擇最大(最小)的那個數,將這個數放到合適的位置。然後拋開這個數的子序列中找最大(最小)的那個數放到合適的位置。然後一直到子序列爲空。

  • 時間複雜度(平均): O(n^2)
  • 時間複雜度(最壞): O(n^2)
  • 時間複雜度(最好): O(n^2)
  • 空間複雜度: O(1)
  • 穩定性: 不穩定
  • 代碼實現:
    /*
    函數功能: 選擇排序
    函數名稱: selectSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    template<typename T>
    void selectSort(T *arr, int len)
    {
        T temp;
        int j, min_index;
        if(len <= 1)
            return;
        for(int i=0; i<len; i++)
        {
            min_index = i;
            for(j=i+1;j<len;j++)
            {
                if(arr[j]<arr[min_index])
                    min_index = j;
            }
            swap(arr, min_index, i);
        }
    }
    

四、希爾排序

  • 原理:

    改進了得插入排序,將待排序的數組根據差量分成若干的的子數組,分別進行插入排序,通過不斷地修改組距,使得分組數逐漸減少,當組距爲1是,就是一個插入排序。

  • 時間複雜度(平均): O(n^1.3)

  • 時間複雜度(最壞): O(n^2)

  • 時間複雜度(最好): O(n)

  • 空間複雜度: O(1)

  • 穩定性: 不穩定

  • 代碼實現

    /*
    函數功能: 希爾排序算法
    函數名稱: shellSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    template<typename T>
    void shellSort(T *arr, int len)
    {
        if(len <= 1)
            return;
        T temp;
        int j, gap = len/2;
        while(gap > 0)
        {
            for(int i=gap; i<len;i++)
            {
                j = i;
                while(j>0)
                {
                    if(arr[j] < arr[j-gap])
                    {
                        swap(arr,j,j-gap);
                        j -= gap;
                    }else{
                        break;
                    }
                }
            }
            gap /= 2;
        }
    }
    

五、快速排序

  • 原理:

    快速排序是先從數據序列中選一個元素,並將序列中所有比該元素小的元素都放到它的右邊或左邊,再對左右兩邊分別用同樣的方法處之直到每一個待處理的序列的長度爲1,處理結束。

  • 時間複雜度(平均): O(nlog2n)
  • 時間複雜度(最壞): O(n^2)
  • 時間複雜度(最好): O(nlog2n)
  • 空間複雜度: O(nlog2n)
  • 穩定性: 不穩定
  • 代碼實現:
    /*
    函數功能: 具體實現快速排序算法
    函數名稱: quickSort_code
    參數: arr -- 傳入數組指針
          strat -- 數組起始下標
          strat -- 數組結尾下標
    返回值: void
    */
    template<typename T>
    void quickSort_code(T *arr, int strat, int end)
    {
    	// strat是數組的開始,將start作爲基數
    	int m = arr[strat];
        // 遞歸結束條件
    	if (strat >= end)
    		return;
    	int i = strat, j = end;
    	while (i != j)
    	{
    		while (j > i&&arr[j] >= m)
    		{
    			j--;
    		}
    		swap(arr,i, j);
    		while (j > i&&arr[i] <= m)
    		{
    			i++;
    		}
    		swap(arr,i,j); 
    	}
    	quickSort_code(arr, strat, i - 1);
    	quickSort_code(arr, i + 1, end);
    }
    
    /*
    函數功能: 調用快速排序算法,保持所有排序參數一致性
    函數名稱: quickSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    template<typename T>
    void quickSort(T *arr, int len)
    {
        if(len <= 1)
            return;
        quickSort_code(arr, 0, len-1);
    }
    

六、歸併排序

  • 原理:

    該算法是採用分治法的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。將兩個有序表合併成一個有序表。

  • 時間複雜度(平均): O(nlog2n)
  • 時間複雜度(最壞): O(nlog2n)
  • 時間複雜度(最好): O(nlog2n)
  • 空間複雜度: O(n)
  • 穩定性: 穩定
  • 代碼實現:
    /*函數功能: 合併兩個有序數組
    函數名稱: merge_achieve
    參數: arr -- 傳入數組指針
          start -- 數組起始下標
          mid -- 數組中間下標
          end -- 數組結尾下標
    返回值: void
    */
    template<typename T>
    void merge_achieve(T *arr, int start, int mid, int end)
    {
        int n1 = mid - start + 1;
        int n2 = end - mid;
        T *left = new T[n1];
        T *right = new T[n2];
    
        // int left[n1], right[n2];
        int i, j, k;
    
        for (i = 0; i < n1; i++)
            left[i] = arr[start+i];
        for (j = 0; j < n2; j++)
            right[j] = arr[mid+1+j];
    
        i = j = 0;
        k = start;
        while (i < n1 && j < n2)
            if (left[i] < right[j])
                arr[k++] = left[i++];
            else
                arr[k++] = right[j++];
    
        while (i < n1) /* left[] is not exhausted */
            arr[k++] = left[i++];
        while (j < n2) /* right[] is not exhausted */
            arr[k++] = right[j++];
    }
    
    
    /*函數功能: 具體實現歸併排序算法
    函數名稱: merge
    參數: arr -- 傳入數組指針
          start -- 數組起始下標
          end -- 數組結尾下標
    返回值: void
    */
    template<typename T>
    void merge(T *arr, int start, int end) // 先排序,再合併
    {
        int mid;
        if (start < end)
        {
            mid = (start + end) / 2;
            merge(arr, start, mid); // 遞歸劃分原數組左半邊array[start...mid]
            merge(arr, mid+1, end); // 遞歸劃分array[mid+1...end]
            merge_achieve(arr, start, mid, end); // 合併
        }
    }
    
    /*函數功能: 調用歸併排序算法
    函數名稱: mergeSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    template<typename T>
    void mergeSort(T *arr, int len)
    {
        // 調用歸併排序函數
        merge(arr, 0, len-1);
    }
    

七、基數排序(桶排序)

  • 原理:

    基數排序算法的基本原理是將待排序的數組中的值,按照位數上的值作大小比較,排序後存入對應角標範圍爲0-9的桶中。每個位數比較排序後,依次從不爲空的桶中取出值合併,成爲一個部分排序後新的數組,作爲更高位數排序的原始數組,直到最終排序完成。

  • 時間複雜度(平均): O(d(r+n))
  • 時間複雜度(最壞): O(d(rd+n))
  • 時間複雜度(最好): O(d(r+n))
  • 空間複雜度: O(rd+n)
  • 穩定性: 穩定
  • 代碼實現:
    /*函數功能: 基數排序(桶排序)算法
    函數名稱: radixSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    template<typename T>
    void radixSort(T *arr, int len)
    {
        if(len <= 1)
            return;
        int i, base = 1;
        T max = arr[0];
        // 求最大數
        for(int i=1; i<len;i++)
        {
            if(arr[i] > max)
                max = arr[i];
        }
        // 動態分配內存,存儲桶中取出的數字
        int *t = new int[len];
    
    
        while (max/base>0)
        {
            int bucket[10] = {0};
            // 統計每個桶中數的個數
            for(i=0; i<len; i++)
            {
                bucket[arr[i] / base % 10]++;
            }
            // 累加每個桶的個數
            for(i=1;i<10; i++)
            {
                bucket[i] += bucket[i-1];
            }
            // 根據每個數對應的bucket的數作爲下標,指定一次桶排新數組
            for(i=len-1; i>=0; i--)
            {
                t[bucket[arr[i] / base % 10] - 1] = arr[i];
                // 考慮一個桶有多個數字,取出一次減1
                bucket[arr[i] / base % 10] --;
            }
            // 更新原數組
            for(i=0; i<len; i++)
            {
                arr[i] = t[i];
            }
    
            base = base * 10;
        }
        delete []t;
    }
    

八、堆排序

  • 原理:

    將待排序的序列構造成一個大頂堆。此時,整個序列的最大值就是堆頂的根節點。將它移走(其實就是將其與堆數組的末尾元素交換,此時末尾元素就是最大值),然後將剩餘的 n-1 個序列重新構造成一個堆,這樣就會得到 n 個元素中次大的值。如此反覆執行,得到一個有序序列。

  • 時間複雜度(平均): O(nlog2n)
  • 時間複雜度(最壞): O(nlog2n)
  • 時間複雜度(最好): O(nlog2n)
  • 空間複雜度: O(1)
  • 穩定性: 不穩定
  • 代碼實現:
    /*函數功能: 對數組進行堆化
    函數名稱: heapify
    參數: tree -- 傳入數組指針
          n -- 數組長度
          i -- 堆化的數組下標值
    返回值: void
    */
    
    template<typename T>
    void heapify(T tree[], int n , int i)
    {
        if (i >= n)
            return;
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        int max = i;
        if(c1 < n && tree[c1] > tree[max])
            max = c1;
        if(c2 < n && tree[c2] > tree[max])
            max = c2;
        if(max != i)
        {
            swap(tree, max,i);
            heapify(tree, n, max);
        }
    }
      
    /*函數功能: 創建二叉堆樹
    函數名稱: build_heap
    參數: tree -- 傳入數組指針
          n -- 數組長度
    返回值: void
    */
    
    template<typename T>
    void build_heap(T tree[], int n)
    {
        // 完全二叉樹的葉子節點=非葉子節點-1
        int last_node = n-1;
        int parent = (last_node-1)/2;
        for(int i=parent; i >= 0; i--)
            heapify(tree, n, i);
    }
    
    
    /*函數功能: 堆排序算法
    函數名稱: heapSort
    參數: arr -- 傳入數組指針
          len -- 數組長度
    返回值: void
    */
    
    template<typename T>
    void heapSort(T *arr, int len)
    {
        build_heap(arr, len);
        for(int i = len - 1; i >= 0; i--)
        {
            swap(arr,i,0);
            heapify(arr, i, 0);
        }
    }
    

排序系統詳情

一、功能展示

在這裏插入圖片描述

二、源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章