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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

归并排序执行次数_十大排序算法,看这篇就够了

發布時間:2025/3/20 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 归并排序执行次数_十大排序算法,看这篇就够了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

排序算法分類[1][2]

  • 比較類排序:通過比較來決定元素間的相對次序,由于其時間復雜度不能突破O(nlogn),因此也稱為非線性時間比較類排序。
  • 非比較類排序:不通過比較來決定元素間的相對次序,它可以突破基于比較排序的時間下界,以線性時間運行,需要開辟額外的存儲空間,因此也稱為線性時間非比較類排序。

十大排序算法的分類簡單排序:冒泡排序和選擇排序是兩個最好理解的排序方法,實現也簡單易懂。插入排序:簡單插入排序基本思想是需要排序位的前部(或后部)的數據都已經排好序,可理解為將一個新數據放入到一個有序數組中;希爾排序是在此基礎上對其進行了優化,因為對一個基本有序的數組來講,插入排序的速度更快。遞歸排序:遞歸是一種算法的實現方式,可以更好的理解算法的實現步驟,當然,遞歸的算法都可以通過循環方法來實現,并且如果遞歸的深度太深,可能對系統內存消耗太大,其性能不如采用循環的方式。非比較類:均采用了一種統計的思想,需要開辟額外的存儲空間。

排序算法的性能

十大排序算法的性能比較穩定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。不穩定:如果a原本在b的前面,而a=b,排序之后 a 可能會出現在 b 的后面。時間復雜度:對排序數據的總的操作次數。反映當n變化時,操作次數呈現什么規律。空間復雜度:是指算法在計算機內執行時所需存儲空間的度量,它也是數據規模n的函數。

冒泡排序

冒泡排序通過循環比較將最大的元素放到最后,因此形象的稱之為“冒泡”過程。從左向右依次兩兩比較大小,若左邊的值大于右邊的值,則兩兩交換,經過一次排序后,最后面的值則為整個數組中最大的值。重復經過n輪遍歷,便可以完成整個數組的排序。
  • 算法描述:
    • ①從第一個元素開始,比較第i個和第i+1個元素
    • ②若i的值大于i+1的值,則交換連個元素,直到i+1為數組的最后一個元素
    • ③再次從第一個元素開始,重復①②工作
  • 算法優化:
    • 經過第一輪比較后,最后面的元素已經排好序,因此第二輪比較時,i+1為數組的倒數第二個元素便可以退出循環了,每經過一輪排序,均可以較少一個比較
    • 可以設置一個標志位,若經過一輪比較,未發生過交換,則說明現在數組已經排好順序了,可以直接退出
  • 算法動圖:

冒泡排序過程
  • 算法實現
void BubbleSort(vector<int> &input_vec) {if (input_vec.empty() || input_vec.size() == 1)return;bool swap_flag = true;for (int i = 0; i < input_vec.size() - 1 && swap_flag; i++){swap_flag = false;for (int j = 0; j < input_vec.size() - i - 1; j++){if (input_vec[j] > input_vec[j + 1]){swap_flag = true;int temp = input_vec[j];input_vec[j] = input_vec[j + 1];input_vec[j + 1] = temp;}}} }

選擇排序

選擇排序通過遍歷查找出最小元素位置,并進行排序。首先在未排序序列中找到最小元素,將其和序列中的第一個元素交換;然后,再從剩余未排序元素中繼續尋找最小元素并進行排序。以此類推,直到所有元素均排序完畢。
  • 算法描述
    • ①遍歷整個數組,找到最小位置元素的位置
    • ②將其和序列的第一個元素進行交換,則第一個位置元素已排好序,對剩余部分繼續排序
    • ③對剩余未排序序列重復①②操作,直至整個序列都排好序
  • 算法動圖

選擇排序過程
  • 算法實現:
void SelectSort(vector<int> &input_vec) {for (int i = 0; i < input_vec.size(); i++){int min = input_vec[i];for (int j = i; j < input_vec.size(); j++){if (input_vec[j] < min){min = input_vec[j];int temp = input_vec[i];input_vec[i] = input_vec[j];input_vec[j] = temp;}}} }

簡單插入排序

插入排序是基于已排序序列,將一個元素插入到有序隊列的合適位置之中。相較于冒泡排序和選擇排序,三種排序的復雜度都較高,達到O(n^2),冒泡和選擇排序也不可能使用到應用實踐中去,都只能停留在理論研究上,而插入排序還是以其原地排序和穩定性能夠在某些特定的場景中使用。在快速排序中,為減少遞歸的深度,可以采用插入排序做優化。
  • 算法描述
    • ①首先對前兩個元素進行比較并排序
    • ②將第三個元素放入到前兩個有序數組的合適位置,完成后,前三個元素為有序數組
    • ③再對下一個元素重復①②步驟,直至所有元素排序完成
  • 算法動圖

插入排序過程
  • 算法實現
void InsertSort(vector<int> &input_vec) {for (int i = 1, k = i; i < input_vec.size(); i++){int pre = i - 1;int current = input_vec[i];for (; pre >= 0 && input_vec[pre] > current; pre--)input_vec[pre + 1] = input_vec[pre];input_vec[pre + 1] = current;} } 對第i個元素來說,前面i-1個元素是拍好順序的,因此,如果前面有序數組中第k(0<=k<=i-1)個元素大于第i個元素,則k~i-1的元素都會大于它,因此,從第i-1位置的元素開始,依次往后挪一位,最后在空的位置將原始的第i個元素的值填入,更好的利用了前部數組的有序條件。

希爾排序[3]

1959年Shell發明,第一個突破O(n2)的排序算法,是簡單插入排序的改進版。對于插入排序來說,一個“基本有序”的數組可以更少的減小循環次數。希爾排序先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。它與插入排序的不同之處在于,它會優先比較距離較遠的元素。希爾排序又叫縮小增量排序。
  • 算法優點
    • 簡單插入排序很循規蹈矩,不管數組分布是怎么樣的,依然一步一步的對元素進行比較,移動,插入,比如[5,4,3,2,1,0]這種倒序序列,數組末端的0要回到首位置很是費勁,比較和移動元素均需n-1次。而希爾排序在數組中采用跳躍式分組的策略,通過某個增量將數組元素劃分為若干組,然后分組進行插入排序,隨后逐步縮小增量,繼續按組進行插入排序操作,直至增量為1。希爾排序通過這種策略使得整個數組在初始階段達到從宏觀上看基本有序,小的基本在前,大的基本在后。然后縮小增量,到增量為1時,其實多數情況下只需微調即可,不會涉及過多的數據移動。
  • 算法描述

希爾排序過程在此我們選擇增量gap=length/2,縮小增量繼續以gap = gap/2的方式,這種增量選擇我們可以用一個序列來表示,{n/2,(n/2)/2...1},稱為增量序列。希爾排序的增量序列的選擇與證明是個數學難題,我們選擇的這個增量序列是比較常用的,也是希爾建議的增量,稱為希爾增量,但其實這個增量序列不是最優的。此處我們做示例使用希爾增量。
  • 算法實現
void ShellSort(vector<int> &input_vec) {int gap = (input_vec.size()) / 2;while (gap >= 1){for (int i = gap; i < input_vec.size(); i++){int pre = i - gap;int current = input_vec[i];for (; pre >= 0 && input_vec[pre] > current; pre -= gap)input_vec[pre + gap] = input_vec[pre];input_vec[pre + gap] = current;}gap /= 2;} }

歸并排序[4][5]

歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為2-路歸并。
  • 算法描述(迭代法)
    • ①申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并后的序列
    • ②設定兩個指針,最初位置分別為兩個已經排序序列的起始位置
    • ③比較兩個指針所指向的元素,選擇相對小的元素放入到合并空間,并移動指針到下一位置
    • ④重復步驟③直到某一指針到達序列尾
    • ⑤將另一序列剩下的所有元素直接復制到合并序列尾
  • 算法描述(遞歸法)
    • ①將序列每相鄰兩個數字進行歸并操作,形成n/2個序列,排序后每個序列包含兩個元素
    • ②將上述序列再次歸并,形成n/4個序列,每個序列包含四個元素
    • ③重復步驟②,直到所有元素排序完畢

歸并排序圖解從上至下為遞歸,從下至上為迭代
  • 算法實現(遞歸法)
void MergeSort(vector<int> &input_vec, int start, int end) {if (start >= end)return;int mid = (start + end) >> 1;recurMergeSort(input_vec, start, mid);recurMergeSort(input_vec, mid + 1, end);int start1 = start, end1 = mid, start2 = mid + 1, end2 = end;vector<int> temp;while (start1 <= mid && start2 <= end)temp.push_back(input_vec[start1] < input_vec[start2] ? input_vec[start1++]: input_vec[start2++]);while (start1 <= mid)temp.push_back(input_vec[start1++]);while (start2 <= end)temp.push_back(input_vec[start2++]);for (int k = 0; k < temp.size(); k++)input_vec[start + k] = temp[k]; }
  • 算法實現(迭代法)
void CArithmetic::MergeSort(vector<int> &input_vec) {for (int step = 1; step <= input_vec.size(); step = step * 2){int len = input_vec.size() % (2 * step) == 0 ? input_vec.size(): input_vec.size() + 2 * step;for (int j = 0; j < len; j += 2 * step){vector<int> temp;temp.clear();int start1 = j, start2 = j + step;while (start1 < j + step && start1 < input_vec.size() &&start2 < j + step * 2 && start2 < input_vec.size())temp.push_back(input_vec[start1] < input_vec[start2] ? input_vec[start1++]: input_vec[start2++]);while (start1 < j + step && start1 < input_vec.size())temp.push_back(input_vec[start1++]);while (start2 < j + step * 2 && start2 < input_vec.size())temp.push_back(input_vec[start2++]);for (int k = 0; k < temp.size(); k++)input_vec[j + k] = temp[k];}} }

快速排序

快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。快速排序使用分治法來把一個串分為兩個子串。
  • 算法描述
    • ①從數列中挑出一個元素,稱為 “基準”(pivot);
    • ②重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數可以到任一邊)。在這個分區退出之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作;
    • ③遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序。
  • 算法動圖

快速排序過程
  • 算法實現
void CArithmetic::recurQuickSort(vector<int> &input_vec, int left, int right) {int i = left, j = right;int temp = input_vec[left];if (i < j){while (i < j){while (i < j && input_vec[j] >= temp)j--;input_vec[i] = input_vec[j];while (i < j && input_vec[i] <= temp)i++;input_vec[j] = input_vec[i];}input_vec[i] = temp;recurQuickSort(input_vec, left, i - 1);recurQuickSort(input_vec, i + 1, right);} }

堆排序[6]

堆排序是利用堆這種數據結構而設計的一種排序算法,堆排序是一種選擇排序,它的最壞,最好,平均時間復雜度均為O(nlogn),它也是不穩定排序。
  • 堆結構

堆結構堆排序的基本思想是:將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然后將剩余n-1個元素重新構造成一個堆,這樣會得到n個元素的次小值。如此反復執行,便能得到一個有序序列了
  • 算法描述
    • ①將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;
    • ②將堆頂元素R[1]與最后一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
    • ③由于交換后新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然后再次將R[1]與無序區最后一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重復此過程直到有序區的元素個數為n-1,則整個排序過程完成。
  • 算法動圖

  • 算法實現
void heap_swap(vector<int> &input_vec, int pos1, int pos2) {if (input_vec.empty() || pos1 >= input_vec.size() || pos2 >= input_vec.size())return;int temp = input_vec[pos1];input_vec[pos1] = input_vec[pos2];input_vec[pos2] = temp; }void heap_copare(vector<int> &input_vec, int parent, int limit) {if (input_vec.empty())return;int ch1 = (parent << 1) + 1, ch2 = (parent << 1) + 2, flag = parent;if (ch1 < limit && input_vec[ch1] > input_vec[flag])flag = ch1;if (ch2 < limit && input_vec[ch2] > input_vec[flag])flag = ch2;if (flag != parent){heap_swap(input_vec, parent, flag);heap_copare(input_vec, flag, limit);} }void HeapSort(vector<int> &input_vec) {if (input_vec.empty() || input_vec.size() == 1)return;//構建最大堆int last = input_vec.size() - 1, parent = (last - 1) / 2;for (int idx = parent; idx >= 0; idx--)heap_copare(input_vec, idx, input_vec.size());//交換并修復堆for (int idx = last; idx >= 0; idx--){heap_swap(input_vec, 0, idx);heap_copare(input_vec, 0, idx);} }

計數排序

計數排序不是基于比較的排序算法,其核心在于將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。 作為一種線性時間復雜度的排序,計數排序要求輸入的數據必須是有確定范圍的整數。
  • 算法描述
    • ①找出待排序的數組中最大和最小的元素;
    • ②統計數組中每個值為i的元素出現的次數,存入數組C的第i項;
    • ③對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加);
    • ④反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1。

  • 算法實現
void CountingSort(vector<int> &input_vec, int min, int max) {if (input_vec.empty() || min > max)return;vector<int> temp;temp.resize(max - min + 1);for (int idx = 0; idx < input_vec.size(); idx++)temp[input_vec[idx] - min]++;int k = 0;for (int idx = 0; idx < temp.size(); idx++)for (int j = 0; j < temp[idx]; j++)input_vec[k++] = idx + min; }

桶排序[7]

桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在于這個映射函數的確定。桶排序 (Bucket sort)的工作的原理:假設輸入數據服從均勻分布,將數據分到有限數量的桶里,每個桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排)。
  • 算法描述
    • ①設置一個定量的數組當作空桶;
    • ②遍歷輸入數據,并且把數據一個一個放到對應的桶里去;
    • ③對每個不是空的桶進行排序;
    • ④從不是空的桶里把排好序的數據拼接起來。
  • 算法圖解

桶排序圖解
  • 算法實現
void BucketSort(vector<int> &input_vec, int min, int max, int bucket_size) {if (input_vec.empty() || min > max || bucket_size <= 0)return;vector<vector<int>> bucket;bucket.resize((max - min + 1) / bucket_size + 1);for (int idx = 0; idx < input_vec.size(); idx++)bucket[(input_vec[idx] - min) / bucket_size].push_back(input_vec[idx]);int k = 0;for (int idx = 0; idx < bucket.size(); idx++){InsertSort(bucket[idx]);for (int j = 0; j < bucket[idx].size(); j++)input_vec[k++] = bucket[idx][j];} }

基數排序

基數排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最后的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。
  • 算法描述
    • ①取得數組中的最大數,并取得位數;
    • ②arr為原始數組,從最低位開始取每個位組成radix數組;
    • ③對radix進行計數排序(利用計數排序適用于小范圍數的特點;
  • 算法動圖

基數排序圖解
  • 算法實現
void CArithmetic::RadixSort(vector<int> &input_vec) {if (input_vec.empty())return;vector<vector<int>> bucket;int flag = true;for (int times = 1, dev = 1, count = 0; flag; times *= 10, dev *= 10){bucket.resize(10);bucket.clear();flag = false;for (int idx = 0; idx < input_vec.size(); idx++){int p = (input_vec[idx] % (10 * times)) / dev;bucket[p].push_back(input_vec[idx]);if (p)count++;}cout << count << endl;if (count != 0){flag = true;int k = 0;for (int idx = 0; idx < bucket.size(); idx++){for (int j = 0; j < bucket[idx].size(); j++){cout << " " << bucket[idx][j];input_vec[k++] = bucket[idx][j];}}cout << endl;}} }

參考

  • ^十大經典排序算法(動圖演示)?https://www.cnblogs.com/onepixel/articles/7674659.html
  • ^排序算法分類?https://www.cnblogs.com/zhousong918/p/10172343.html
  • ^圖解排序算法之希爾排序?https://www.cnblogs.com/chengxiao/p/6104371.html
  • ^圖解排序算法之歸并排序?https://www.cnblogs.com/chengxiao/p/6194356.html
  • ^【算法】排序算法之歸并排序?https://zhuanlan.zhihu.com/p/124356219
  • ^圖解排序算法之堆排序?https://www.cnblogs.com/chengxiao/p/6129630.html
  • ^【圖解數據結構】 一組動畫徹底理解桶排序?https://www.jianshu.com/p/e605fe7a23b0
  • 總結

    以上是生活随笔為你收集整理的归并排序执行次数_十大排序算法,看这篇就够了的全部內容,希望文章能夠幫你解決所遇到的問題。

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