好幾天沒看《演算法導論》,今天看了一天的排序演算法,印象第一的是基數演算法,因為居然違反我的乙個常識,它採用的是最低有效位進行排序的。插入排序、歸併排序、堆排序、快速排序,這些都是比較排序演算法:它們都是通過對元素進行比較操作來確定輸入陣列的有序次序,這些演算法可以用決策樹模型分析,可以證明任意比較排序演算法排序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...