排序算法
選擇排序(O(n^2))
從i=0開始循序n次,每次從(i, n)中尋找最小的數(shù),用minIndex記錄最小值的下標(biāo),然后與a[i]的值進(jìn)行交換。
for( int i=0; i<n; i++ ) {
int minIndex = i;
// 從(i, n)中尋找最小的數(shù)
for( int j=i+1 ; j<n; j++ ) {
if(a[j] < a[minIndex] ) {
minIndex = j;
}
}
swap(a[i] , a[minIndex]);//交換兩個(gè)值
}-
插入排序(O(n^2))
思路:在得到要排序的數(shù)組以后,講數(shù)組分為兩個(gè)部分,數(shù)組的第一個(gè)元素為一個(gè)部分,剩下的元素為一部分,然后從數(shù)組的第二個(gè)元素開始,和該元素以前的所有元素比較,如果之前的元素沒有比該元素大的,那么該元素的位置不變,如果有元素的值比該元素大,那么記錄相愛他所在的位置;例如i,該元素的位置為j,則將從i到j(luò)位置上的所有元素往后移動(dòng)一位,然后將k位置上的值移動(dòng)到i位置上。這樣就找到了j所在的位置。每一個(gè)元素都這樣進(jìn)行,最終就會(huì)得到排好順序的數(shù)組。
for( int i = 1; i < n; i++) {
for( int j = i; j > 0; j--) {
if ( a[j] < a[j-1])
swap( a[j], a[j-1];//交換兩個(gè)值的位置
else
braak;
}
}這樣的插入排序其實(shí)比選擇排序要慢,下面來(lái)改進(jìn)一下:
for( int i = 1; i < n; i++) { int t = a[i]; int j; for( j = i; j > 0 & a[j-1] > t; j--) { a[j] = a[j-1]; } a[j] = t; }
改進(jìn)后,在有序性非常強(qiáng)(近乎有序的)的數(shù)組排序下,插入排序要比選擇排序更優(yōu)越。
冒泡排序(O(n^2))
思路:將** 相鄰 **的兩個(gè)數(shù)比較,將較小的數(shù)調(diào)到前頭;有n個(gè)數(shù)就要進(jìn)行n-1趟比較,第一次比較中要進(jìn)行n-1次兩兩比較,在第j趟比較中,要進(jìn)行n-j次兩兩比較。
//排序,從a[0]開始排,從小到大
for (i = 0; i < n-1; i++) {
for (j = i + 1; j < n-1-i; j++)
{
if (str[ j ] > str[ j+1 ])
{
swap(str[ j ], str[ j+1 ]);
}
}
}
-
歸并排序(O(nlogn))
設(shè)兩個(gè)有序的子序列(相當(dāng)于輸入序列)放在同一序列中相鄰的位置上:array[low..m],array[m + 1..high],先將它們合并到一個(gè)局部的暫存序列 temp (相當(dāng)于輸出序列)中,待合并完成后將 temp 復(fù)制回 array[low..high]中,從而完成排序。在具體的合并過(guò)程中,設(shè)置 i,j 和 p 三個(gè)指針,其初值分別指向這三個(gè)記錄區(qū)的起始位置。合并時(shí)依次比較 array[i] 和 array[j] 的關(guān)鍵字,取關(guān)鍵字較?。ɑ蜉^大)的記錄復(fù)制到 temp[p] 中,然后將被復(fù)制記錄的指針 i 或 j 加 1,以及指向復(fù)制位置的指針 p加 1。重復(fù)這一過(guò)程直至兩個(gè)輸入的子序列有一個(gè)已全部復(fù)制完畢(不妨稱其為空),此時(shí)將另一非空的子序列中剩余記錄依次復(fù)制到 array 中即可。
舉例:-
自頂向下
轉(zhuǎn)載圖片.png -
自底向上
轉(zhuǎn)載圖片.png 歸并算法的優(yōu)化
在數(shù)據(jù)近乎有序的情況下,插入排序依舊要快于歸并排序??梢栽谶f歸的情況下修改退出遞歸的條件,在數(shù)據(jù)r-l小于一定數(shù)量比如15的時(shí)候,我們改為調(diào)用插入排序。
-
快速排序O(N*logN)
基本原理:
1.獲得待排序數(shù)組a
2.選取一個(gè)合適的數(shù)字p(一般來(lái)說(shuō)就選取數(shù)組或是子數(shù)組的第一個(gè)元素)作為排序基準(zhǔn)
3.將待排序數(shù)組a中比基準(zhǔn)p小的放在p的左邊,比基準(zhǔn)p大的放在p的右邊
4.從第3步獲得的兩個(gè)子數(shù)組arr1跟arr2
5.判斷arr1或arr2中是否只有一個(gè)元素,如果只有一個(gè)元素則返回此元素,否則就將arr1(或是arr2)代回到第1步中繼續(xù)執(zhí)行
注意:在幾近有序的情況下,快速排序非常慢,他的深度可能原因大于logN。
-
堆排序O(N*logN)
完全二叉樹:若設(shè)二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個(gè)數(shù),第 h 層所有的結(jié)點(diǎn)都連續(xù)集中在最左邊,這就是完全二叉樹。滿二叉樹:一顆深度為k且有2^k-1個(gè)結(jié)點(diǎn)的二叉樹稱為滿二叉樹。 除葉子結(jié)點(diǎn)外的所有結(jié)點(diǎn)均有兩個(gè)子結(jié)點(diǎn)。節(jié)點(diǎn)數(shù)達(dá)到最大值。所有葉子結(jié)點(diǎn)必須在同一層上。
最大堆:根結(jié)點(diǎn)的鍵值是所有堆結(jié)點(diǎn)鍵值中最大者,且每個(gè)結(jié)點(diǎn)的值都比其孩子的值大。(最大堆必須是完全二叉樹)
Paste_Image.png-
索引堆
元素的值不變,只是比較元素的值,然后構(gòu)建堆的時(shí)候,交換的是元素對(duì)應(yīng)的索引值。舉例如下:
初始時(shí):
初始情況
構(gòu)造索引堆:
最大索引堆.png
-
二叉樹
二分查找法
用數(shù)組保存數(shù)據(jù),保證有序。二分查找速度很快,但是僅限于查找。因?yàn)椴迦氲臅r(shí)候要保證有序,所以要往后移動(dòng)數(shù)據(jù)以便插入。查找復(fù)雜度 O(logn) ,插入復(fù)雜度 O(n) 。-
二叉查找樹
二叉查找樹(Binary Search Tree),也稱有序二叉樹(ordered binary tree),排序二叉樹(sorted binary tree),是指一棵空樹或者具有下列性質(zhì)的二叉樹:
1.若任意節(jié)點(diǎn)的左子樹不空,則左子樹上所有結(jié)點(diǎn)的值均小于它的根結(jié)點(diǎn)的值;
2.任意節(jié)點(diǎn)的右子樹不空,則右子樹上所有結(jié)點(diǎn)的值均大于它的根結(jié)點(diǎn)的值;
3.任意節(jié)點(diǎn)的左、右子樹也分別為二叉查找樹。
4.沒有鍵值相等的節(jié)點(diǎn)(no duplicate nodes)。-
二叉搜索樹的前中后序遍歷:
二叉搜索樹的遍歷方式.png
二叉搜索樹 的查找和搜索在平均情況下時(shí)間復(fù)雜度都能達(dá)到 O(logn) ,而且能保證數(shù)據(jù)有序。 二叉搜索樹 的中序遍歷就是數(shù)據(jù)的順序。如果數(shù)據(jù)是逆序,或者順序,那么這棵樹就會(huì)發(fā)生一邊倒的情況使復(fù)雜度直接達(dá)到 O(n) ,就如同快排中選擇到糟糕的主元(最大或者最小)。
-
廣度優(yōu)先遍歷 (O(n))
二叉搜索樹.png
又叫寬度優(yōu)先搜索或橫向優(yōu)先搜索,是從根結(jié)點(diǎn)開始沿著樹的寬度搜索遍歷,上面二叉樹的遍歷順序?yàn)椋篈BCDEFG.可以利用隊(duì)列實(shí)現(xiàn)廣度優(yōu)先搜索。
深度優(yōu)先搜索
深度優(yōu)先搜索(Depth First Search)是沿著樹的深度遍歷樹的節(jié)點(diǎn),盡可能深的搜索樹的分支。以上面二叉樹為例,深度優(yōu)先搜索的順序?yàn)椋篈BDECFG。二分搜素樹的結(jié)點(diǎn)刪除
最小值:在左子樹盡頭
最大值:在右子叔盡頭
在刪除結(jié)點(diǎn)時(shí),如果刪除的結(jié)點(diǎn)有左右子樹,那么應(yīng)該尋找該結(jié)點(diǎn)右子樹中的最小值結(jié)點(diǎn)來(lái)代替他。
-
圖
無(wú)權(quán)圖
有權(quán)圖
-
鄰接表和鄰接矩陣
- 鄰接表:適合表示稀疏圖
- 鄰接矩陣:適合表示稠密圖
圖的深度優(yōu)先遍歷
圖的廣度優(yōu)先遍歷
可以獲取無(wú)權(quán)圖的最短路徑,閉環(huán)判斷-
最小生成樹(有權(quán)圖+無(wú)向圖+連通圖)
應(yīng)用:電纜布線、電路設(shè)計(jì)、網(wǎng)絡(luò)設(shè)計(jì)- lazy prim算法
- 優(yōu)化prim算法,利用最小索引堆優(yōu)化
- kruskal算法:將所有邊的權(quán)值進(jìn)行由小到大排序,依次選擇權(quán)值小的邊并且這些邊之間不能構(gòu)成閉環(huán)。
-
單元最短路徑算法
- dijkstra算法(圖中不能有負(fù)權(quán)邊)