排序演算法引導

2021-05-23 03:17:51 字數 4013 閱讀 9200

簡介:

有許多的關於資料計算的應用程式中都用到演算法。甚至在我們開始運算資料之前,演算法的重要性就浮在我們眼前了。比如,我們在查詢**上的人時,必須按從高到低的順序。我們必須給業績最好的員工最好的獎金,這就要求我們必須從高到低,或從大到小的順序排列事物。

比如,我們查詢資料庫時,排序時,要加上

order by

語句。我們尋找手機上的某本書時,必須從已經排好序的佇列中找。如果你想高效的用二分查詢法從陣列中查詢某個元素,你可能得排序好整個陣列。有個問題要求我們必須以字典順序返回結果時,那麼我們想到要排序。

一般考慮:

假設有一種人,分給他們每人一副大亂順序的撲克,要求他們按從大到小排序。一些人可能按樁的結構排,一些人還可能把牌都放在桌子上排好序,還有一些人可能在手中就排好序了。但他們所用的時間可能不一樣。可能會出現很多樣的排序方式。

在我們排序時,我們必須有幾件事要考慮,首先就是時間。

另乙個考慮的問題就是所用到的記憶體空間。

另一點要考慮的就是穩定性。

氣泡排序:

首先我們想到的就是氣泡排序,他的時間複雜度為o(n

²),但他要求的記憶體空間也很低。

for (int i = 0; i < data.length; i++)

for (int j = 0; j < data.length - 1; j++)

if (data[j] > data[j + 1])

插入排序:

每次將乙個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子檔案中的適當位置,直到全部記錄插入完成為止。

for (int i = 0; i <= data.length; i++)

比如有這麼一組資料,插入排序的過程為:

插入排序的優點就是我們只考慮要插入的元素。待排序元素已從小到大排好序(正序)或接近排好序時,所用的比較次數和移動次數較少。

歸併排序:

遞迴的歸併排序:思想就是把要排序的陣列分成

2部分,並且單獨的對他們進行排序,然後比較這

2個陣列裡的第乙個元素,把小的那個元素從此陣列裡刪除新增到結果陣列裡。

int mergesort (int data) else if (rptr == right.length) else if (left[lptr] < right[rptr]) else

dptr++;

}return result;

}沒一次遞迴所用的時間複雜度為

0(n),

總共進行了

0(log n)

次,因此時間複雜度為

0(n * log n)

堆排序在堆排序中,我們創造乙個堆的資料結構,它就像一棵樹一樣,最小的元素始終在根節點上。執行堆排序時,所以的元素必須都插入到堆中,然後把根節點從堆移到結果陣列中。

/*ary是儲存記錄的陣列, start是需要調整為大頂堆的根記錄下標, end是

它的最後乙個葉子記錄的下標。

注意,傳入的start到end之間的記錄,除去根記錄,根記錄的左右子二叉樹都

是大頂堆,要完全符合大頂堆的性質呼叫此函式才有效。

下面函式要做的就是調整以start為根記錄,end為最後乙個葉子記錄的完全二叉樹為大頂堆。

*/void heapify(int ary, unsigned int start, unsigned int end)

else

}/* 現在max中是儲存了左右子記錄中(假設存在)關鍵字值最大的下標 */

if (ary[start] < ary[max])

else

left = start * 2;

right = start * 2 + 1;

}/* 調整到最二叉樹的最後乙個葉子結點上,二叉樹也符合大頂堆性質, 調整結束 */

}/* 進行堆排序,完成後ary中的記錄下標從1到size,它們的關鍵字值是非遞減的 */        

void heapsort(int ary, unsigned int size)}/*

調整整棵二叉樹(完全無序狀態)使之成為大頂堆。

策略:首先這課二叉樹的結構是完全二叉樹,我們可以從最後乙個非葉子記錄調整,

直到整棵二叉樹的根記錄。

比如二叉樹有size個結點記錄,那麼最後乙個非葉子結點的下標就

是size / 2(取整),我們就從size / 2, size / 2 - 1, ... ,

直到調整以1為下標的整棵二叉樹為大頂堆。

因為以最後乙個葉子記錄為根的二叉樹必定符合呼叫函式heapify的條件,

位於同一層的非葉子結點必定也符合呼叫條件,heapify函式處理完後這一層後,

上一層的非葉子記錄對應的二叉樹也符合了呼叫條件,

這樣直到以整棵二叉樹的根(即ary)記錄為根的二叉樹也符合大頂堆的性質,

整個大頂堆就建立起來。

現在整棵二叉樹的根記錄就是該記錄集中關鍵字值最大的記錄。

*/void buildheap(int ary, unsigned int size)}/*

演算法分析:

1.堆排序的時間,主要由建立初始堆和反覆重建堆這兩部分的時間開銷構成,

它們均是通過呼叫heapify實現的。

堆排序的最壞時間複雜度為o(n * lgn)。堆排序的平均效能較接近於最壞效能。

buildheap最壞情況下時間複雜度為o(n),但是for迴圈在最壞情況下卻

要o(n * lgn)的時間。

2.由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的檔案。

3.堆排序是就地排序,輔助空間為o(1)。

4.它是不穩定的排序方法。

*/堆排序的時間複雜度為o(n

* log

n).

源文件

快速排序

快速排序像哈夫曼樹類似,首先把排序的陣列分成

2部分,使前部分小於關鍵字,後部分大於關鍵字。然後遞迴排序

void quicksort(seqlist r,int low,int high)

} //quicksort

int partition(seqlist r,int i,int j)

//endwhile

r[i]=pivot

; //基準記錄已被最後定位

return i;

} //partition

源文件

快速排序的最壞時間複雜度應為0(n2),最好時間複雜度為o(nlgn)。

基樹排序

基數排序是非比較排序演算法

,演算法的時間複雜度是

o(n).

相比於快速排序的

o(nlgn),

從表面上看具有不小的優勢

.但事實上可能有些出入

,因為基數排序的

n可能具有比較大的係數

k.因此在具體的應用中

,應首先對這個排序函式的效率進行評估.

基數排序的主要思路是

,將所有待比較數值(注意

,必須是正整數

)統一為同樣的數字長度

,數字較短的數前面補零

. 然後

, 從最低位開始

, 依次進行一次

穩定排序

(blog

介紹的計數排序演算法

, 因為

每個位可能的取值範圍是固定的從0到

9).這樣從最低位排序一直到最高位排序完成以後

, 數列就變成乙個有序序列.

比如這樣乙個數列排序

: 342 58 576 356,

以下描述演示了具體的排序過程

(紅色字型表示正在排序的數字)

第一次排序(個位

): 3 4 2

5 7 6

3 5 6

0 5 8

第二次排序(十位

): 3 4

2 3 5

6 0 5

8 5 7

6 第三次排序(百位

): 05 8 3

4 2

35 6 5

7 6

結果: 58 342 356 576

源文件

源文件

排序演算法 排序演算法彙總

排序演算法無疑是學習資料結構中的重點內容,本文將給出排序演算法的彙總。下面是具體的實現 include include include define n 1000000 int array n int temp n 1 氣泡排序 void bubblesort int a,int n if tag ...

排序演算法 排序演算法彙總

排序演算法無疑是學習資料結構中的重點內容,本文將給出排序演算法的彙總。下面是具體的實現 include include include define n 1000000 int array n int temp n 1 氣泡排序 void bubblesort int a,int n if tag ...

排序演算法 排序演算法彙總

排序演算法無疑是學習資料結構中的重點內容,本文將給出排序演算法的彙總。下面是具體的實現 include include include define n 1000000 int array n int temp n 1 氣泡排序 void bubblesort int a,int n if tag ...