日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

七、排序(1)

發布時間:2025/3/19 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 七、排序(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、排序的概述

1、最經典、最常用的排序方法:

  • 冒泡排序、插入排序、選擇排序、歸并排序、快速排序、計數排序、基數排序、桶排序。

2、分類:

排序方法時間復雜度是否基于比較適用性
1冒泡、插入、選擇O(n2)適合小規模數據排序
2快排、歸并O(nlogn)適合大規模的數據排序
3桶、計數、基數O(n)×

思考: 插入排序和冒泡排序具有相同的時間復雜度,但在實際開發中,更傾向于使用插入排序?
解:冒泡程序中的交換操作:需要3個賦值操作,而插入排序的移動操作:只需一個賦值操作。

3、分析“排序算法”

(1)執行效率

  • 最好情況、最壞情況、平均情況時間復雜度
    • 原始數據的形態——有序度
  • 時間復雜度的系數、常數、低階
    • 對同一階時間復雜度的排序算法性能對比時,需考慮系數、常數、低階
  • 比較 “次數和交換(或移動)” 次數

(2)內存消耗——空間復雜度

原地排序(sorted in place)——特指空間復雜度為O(1)的排序算法

(3)穩定性

穩定性:若待排序的序列中存在值相等的元素,經過排序之后,相等元素之間原有的先后順序不變

穩定性重要性:可針對對象的多種屬性進行有優先級的排序。

示例:電商交易系統中的“訂單”排序。

  • 目標:訂單有兩個屬性,一個是下單時間,另一個是訂單金額。希望按照金額從小到大對訂單數據排序。對于金額相同的訂單,希望按照金額從小到大對訂單數據排序。
  • 實現:借助穩定排序算法。先按照下單時間給訂單排序,注意是按照下單時間,不是金額。排序完成之后,我們用穩定排序算法,按照訂單金額重新排序。兩遍排序之后,我們得到的訂單數據就是按照金額從小到大排序,金額相同的訂單按照下單時間從早到晚排序的。

二、冒泡算法(Bubble Sort)

1、基本思想

兩兩比較相鄰記錄的關鍵字,若反序則交換,直到沒有反序的記錄為止。

2、示例

目標:數組{4,5,6,3,2,1}——從小到大排序
過程:

  • 第一次冒泡操作的詳細過程:
  • 完成排序的所有操作:

3、優化

當某次冒泡操作已經沒有數據交換時,說明已經達到完全有序,不需要再繼續執行后面的冒泡操作。

4、實現

(1)基于數組的實現

#include <iostream> using namespace std;/** 冒泡排序——從小到大排序** 參數說明:* a -- 待排序的數組* n -- 數組的長度*/ void bubbleSort(int *a, int n) {int i,j,tmp;for(i = 0; i < n-1; i++){for(j = 0; j < n-1-i;j++){if(a[j] > a[j+1]){// 交換 a[j] 與 a[j+1]tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;}}} }/** 冒泡排序(改進版)——從小到大排序** 參數說明:* a -- 待排序的數組* n -- 數組的長度*/ void bubbleSort1(int *a, int n) {int i,j,tmp;int flag; // 標記for(i = 0; i < n-1; i++){flag = 0;for(j = 0; j < n-1-i;j++){if(a[j] > a[j+1]){tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;flag = 1;}}// 若沒發生交換,則說明數列已有序。if (flag == 0)break;} }int main() {int i;int a[] = {2,4,3,1,6,5};int len = (sizeof(a)/sizeof(a[0]));cout<<"Before Sort:";for(i = 0; i < len; i++)cout<< a[i]<<" ";cout<<endl;// 傳統方法bubbleSort(a, len); // 傳統方法// 改進方法:即若內循環中不發生交換,則說明數列已有序// bubbleSort1(a,len);cout<<"After Sort:";for(i = 0; i < len; i++)cout<< a[i]<<" ";cout<<endl;return 0; }

(2)基于C++模板實現冒泡排序

/** 基于C++模板實現:冒泡排序——從小到大排序** 參數說明:* a -- 待排序的數組* n -- 數組的長度*/ #include <iostream> using namespace std; template<typename T> //整數或浮點數皆可使用 void bubble_sort(T arr[], int len) {int i, j; T temp;for (i = 0; i < len - 1; i++)for (j = 0; j < len - 1 - i; j++)if (arr[j] > arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;} }int main() {int arr[] = { 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 };int len = (int) sizeof(arr) / sizeof(*arr);bubble_sort(arr, len);for (int i = 0; i < len; i++)cout << arr[i] << ' ';cout << endl;float arrf[] = { 17.5, 19.1, 0.6, 1.9, 10.5, 12.4, 3.8, 19.7, 1.5, 25.4, 28.6, 4.4, 23.8, 5.4 };len = (int) sizeof(arrf) / sizeof(*arrf);bubble_sort(arrf, len);for (int i = 0; i < len; i++)cout << arrf[i] << ' ';return 0; }

5、性能分析

(1)原地排序算法

  • 冒泡過程中只涉及相鄰數據的交換操作 ==》需要常量級的臨時空間,即空間復雜度為 O(1)

(2)穩定排序算法

  • 為保證冒泡排序算法的穩定性 ==》當有相鄰的兩個元素大小相等的時候,不做交換 ==》穩定

(3)時間復雜度

  • 最好情況時間復雜度(有序時):O(n)
  • 最壞情況時間復雜度(逆序時):O(n2)
  • 平均情況時間復雜度:O(n2)
    • 最壞情況下,初始狀態的有序度是 0,所以要進行 n*(n-1)/2 次交換。最好情況下,初始狀態的有序度是 n*(n-1)/2,就不需要進行交換。
    • 平均情況下,需要 n*(n-1)/4 次交換操作。

平均情況時間復雜度(加權平均期望時間復雜度)——通過“有序度” 和 “逆序度” 兩個概念進行分析

  • 有序度:數組中具有有序關系的元素對的個數。
    有序元素對用數學表達式表示:a[i] <= a[j], 如果 i < j
    示例:
    {2,4,3,1,5,6} =》有序度為11,分別為: (2,4)、(2,3)、(2,5)、(2,6)、(4,5)、(4,6)、(3,5)、(3,6)、(1,5)、(1,6)、(5,6)
    {1,2,3,4,5,6}=》有序度為n*(n-1)/2,稱為滿有序度
  • 逆序度:逆序元素對:a[i] > a[j], 如果 i < j。
  • 逆序度 = 滿有序度 - 有序度。
  • 排序的過程是一種增加有序度,減少逆序度的過程,最后達到滿有序度。
  • 交換次數總是確定的,即為逆序度,也就是:n*(n-1)/2 – 初始有序度
  • 三、插入排序(Insertion Sort)

    1、基本思想

    將一個記錄插入到已經排好序的有序表中,從而得到一個新的、記錄數增1的有序表。

    (1)過程概述

    插入排序在實現上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復把已排序元素逐步向后挪位,為最新元素提供插入空間。

    (2)具體算法描述:

  • 從第一個元素開始,該元素可以認為已經被排序
  • 取出下一個元素,在已經排序的元素序列中從后向前掃描
  • 如果該元素(已排序)大于新元素,將該元素移到下一位置
  • 重復步驟3,直到找到已排序的元素小于或者等于新元素的位置
  • 將新元素插入到該位置后
  • 重復步驟2~5
  • 2、示例

    原數據:{4,5,6,1,3,2}
    排序過程:其中左側是已排序區間,右側是未排序區間。

    分析:滿有序度是 n*(n-1)/2=15,初始序列的有序度是 5,所以逆序度是 10。插入排序中,數據移動的個數總和也等于10 = 3+3+4。

    3、實現

    void insertSort(int a[], int len) { int tmp,j;for(int i = 1; i < len; i++){tmp = a[i]int j = i -1;while(tmp < a[j]){a[j+1] = a[j];j--;} a[j+1] = tmp;} }

    4、分析

    (1)原地排序算法

    • 空間復雜度為 O(1) ==》原地排序算法

    (2)穩定排序算法

    • 對于值相同的元素,可以選擇將后面出現的元素,插入到前面出現元素的后面。==》保持原有前后順序,也就是穩定的排序算法

    (3)時間復雜度

    • 最好情況時間復雜度(數據已經有序):O(n)
    • 最壞情況時間復雜度:O(n2)
    • 平均時間復雜度:O(n2)
      • 對于插入排序來說,每次插入操作(時間復雜度為O(n))都相當于在數組中插入一個數據,循環執行 n 次插入操作

    四、選擇排序(Selection Sort)

    1、基本思想

    從未排序區間中找到最小的元素,將其放在已排序區間的末尾,也就是與未排序區間的第一個元素進行交換。


    分析:
    (1)原地排序算法 《= 空間復雜度:O(1)
    (2)最好情況時間復雜度、最壞情況和平均情況時間復雜度都為 O(n2
    (3)非穩定排序:選擇排序每次都要找剩余未排序元素中的最小值,并和前面的元素交換位置,這樣破壞了穩定性。

    2、實現

    void selectSort(int a[], int len) { int min,tmp;for(int i = 0; i < len - 1;i++){min = i; // 假設最小元素的下標for(int j = i + 1; j < n; j++){if(a[j] < a[min])min = j;}// 若數組中真的存在比假設的元素還要小的元素,則交換if(i != min){tmp = a[i];a[i] = a[min];a[min] = tmp;}} }

    歸并排序和快速排序都用到了分治思想,非常巧妙。
    ==》可以借鑒這個思想,來解決非排序的問題
    比如:如何在 O(n) 的時間復雜度內查找一個無序數組中的第 K 大元素?

    總結

    以上是生活随笔為你收集整理的七、排序(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。