演算法導論 比較排序演算法筆記

2021-09-09 03:12:43 字數 3929 閱讀 6575

好幾天沒看《演算法導論》,今天看了一天的排序演算法,印象第一的是基數演算法,因為居然違反我的乙個常識,它採用的是最低有效位進行排序的。
插入排序、歸併排序、堆排序、快速排序,這些都是比較排序演算法:它們都是通過對元素進行比較操作來確定輸入陣列的有序次序,這些演算法可以用決策樹模型分析,可以證明任意比較排序演算法排序n個元素的最壞情況執行時間的下界為omega(nlgn),其中堆排序和歸併排序是漸進最優的比較排序演算法。

演算法 最壞情況執行時間

平均情況/

期望執行時間

插入排序(原址)

theta(

n^2)

theta(

n^2)

歸併排序

theta(

nlgn

)theta(

nlgn

)堆排序(原址)

theta(

nlgn

)--------

快速排序(原址)

theta(

n^2)

theta(

nlgn

)期望)

堆排序的時間複雜度和歸併排序一樣,都是o(nlgn),另外它具有插入排序的空間原址性優點,即任何時候都只需要常數個額外的空間元素儲存臨時資料。

堆排序中主要是引入了一種稱為「堆」的資料結構來進行資訊管理。這裡的(二叉)堆可以看作是乙個近似的完全二叉樹。樹上的每乙個結點對應陣列中的乙個元素,如圖1所示。

二叉堆可以分為兩種形式:最大堆和最小堆。因為在堆排序中應用的是最大堆,所以這裡只說最大堆,最大堆中是指除根以外的所有結點i都要滿足:

a[parent[i]]>=a[i],即某個結點的值至多與其父節點一樣大。

兩個性質:

乙個包含n個元素的堆可以看著一顆完全二叉樹,那麼該堆的高度是o(lgn),而且堆結構上的一些基本操作的執行時間至多與樹的高度成正比,即時間複雜度o(lgn);

當用陣列表示儲存n個元素的堆時,葉結點下標分別是[n/2]+1,[n/2]+2,…,n。

偽**:

heapsort(a)

bulid-heap(a)

for i = a.length downto 2

exchange a[1] with a[i]

length-size=a.length-size-1

heapify(a,1)

下面分別解析上面**呼叫的子過程

這個子過程是維護最大堆,被不斷的呼叫。

這個子過程是採用自底向上建堆的過程,裡面用到了上文的性質2。

具體**實現過程:

#include #include #include using namespace std;

int parent(int);

int left(int);

int right(int);

void max_heapify(int , int, int);

void build_max_heap(int , int);

void print(int , int);

void heapsort(int , int);

/*父結點*/

int parent(int i)

/*左子結點*/

int left(int i)

/*右子結點*/

int right(int i)

/*單一子結點最大堆積樹調整*/

void max_heapify(int a, int i, int heap_size)

else

if(r < heap_size && a[r] > a[largest])

if(largest != i)

} /*建立最大堆積樹*/

void build_max_heap(int a,int heap_size)}

/*印出樹狀結構*/

void print(int a, int heap_size)

printf("\n");}

/*堆積排序程式碼*/

void heapsort(int a, int heap_size)

print(a, heap_size);}

/*輸入資料並做堆積排序*/

int main(int argc, char* ar**)

; heapsort(a, heap_size);

system("pause");

return 0;

}

另乙個**:

#include using namespace std;

/* #堆排序#%

#陣列實現#%

*///#篩選演算法#%

void sift(int d, int ind, int len)

}return;}

void heap_sort(int d, int n)}

int main()

; //#qq#%

heap_sort(a, sizeof(a) / sizeof(*a));

for(int i = 0; i < sizeof(a) / sizeof(*a); i++)

cout << endl;

return 0;

}

上面的堆排序是乙個優秀的演算法,但是在實際應用中,應用更多的卻是快速 排序。快速排序演算法的最壞情況時間複雜度為o(n^2),雖然最壞情況的時間複雜度很差,但是它的平均效能卻非常好,它的期望時間複雜度是o(nlgn),而且o(nlgn)中隱含的常數因子非常小。另外它還能進行原址排序,在虛擬環境下也能很好地工作。快速排序同歸並排序一樣,都是基於分治思想的,對乙個典型的子陣列a[p..r]進行快速排序的三步分治過程如下:

偽**:

quicksort(a,p,r)

if p < r

q=partition(a,p,r)

quicksort(a,p,q-1)

quicksort(q+1,r)

上面演算法的關鍵部分是partition過程,它實現了對子陣列的原址重排。

具體**實現:

#include using std::swap;

int partition(int* array, int left, int right)

swap(array[right], array[index]);

return index;}

void qsort(int* array, int left, int right)

演算法導論 比較排序演算法對比實驗

演算法導論 這本書介紹了5種比較排序演算法 插入排序 氣泡排序 歸併排序 堆排序 快速排序。我們現在通過實驗來對比這5種排序演算法的執行時間。用隨機數發生器生成不同長度的陣列,將每種演算法應用於不同長度的陣列,統計程式的執行時間,從而得得每種演算法的期望執行時間隨輸入規模的變化曲線。1.全部5種演算...

演算法複習筆記 排序演算法比較

最近正好複習複習演算法,於是從排序演算法開始做乙個總結。以下的 均為原創,如果有任何問題,歡迎指正。簡單來講,排序演算法的實質是將長度為n的陣列中的數字按照從小到大或者從大到小的順利排列。簡而言之,在不考慮演算法的情況下,我們可以把排序抽象為如下的乙個函式 array表示t型別的乙個陣列,num表示...

堆排序演算法分析 《演算法導論》學習筆記

max heapify a,i 1 l left i 2 r right i 3ifl heap size a and a l a i 4thenlargest l 5elselargest i 6ifr heap size a and a r a largest 7thenlargest r 8i...