計算機考研復試面試常問問題 數據結構篇(下)
注意:有人在閑魚上盜賣我的資料,而且還有很多同學買了,請各位擦亮雙眼,我是整理出來免費分享給大家的!
大家請多點贊和評論,這樣后面的同學更容易百度到,不至於被人盜賣,我就不加水印影響大家使用了!
第一次整理,度不好控制,有不好的地方希望大家理解,后面可能會改進,造福今年之后的同學們!
需要pdf直接打印版,可在公眾號"程序員寶藏"回復復試上岸獲取(會持續更新)
在復習過程中,我用心查閱並整理了在考研復試面試中可能問到的大部分問題,並分點整理了答案,可以直接理解背誦並加上自己的語言潤色!極力推薦打印下來看,效率更高!
聲明:一些邊邊角角的沒有收集,畢竟是考研面試,不是筆試,這樣也能減輕大家的負擔!
此系列一共有8篇:編程語言篇**|數據結構篇|操作系統篇|組成原理篇|計算機網絡篇|數據庫篇|軟件工程篇|計算機專業英語篇**(還未全部完成,敬請期待,你們的支持和關注是我最大的動力!)
個人整理,不可用於商業用途,轉載請注明出處。
需要408電子書2021版,可在公眾號"程序員寶藏"回復408電子書獲取
需要408初試視頻2021版,可在公眾號"程序員寶藏"回復408視頻獲取
需要復試機試視頻,可在公眾號"程序員寶藏"回復機試必過獲取
加油,大家都可以上岸!!!讓我們一起努力!!!
快速喚起記憶知識框架:
19.樹與二叉樹的相關概念?
樹是非線性結構,其元素之間有明顯的層次關系。在樹的結構中,每個節點都只有一個前件稱為父節點,沒有前件的節點為樹的根節點,簡稱為樹的根;每個節點可以有多個后件成為節點的子節點,沒有后件的節點稱為葉子節點。
在樹的結構中,一個節點所擁有的子節點個數稱為該節點的度,樹中最大的節點的度為樹的度,樹的最大的層次稱為樹的深度
二叉樹:二叉樹是另一種樹形結構,其特點是每個結點至多只有兩棵子樹,並且二叉樹的子樹有左右之分,其次序不能任意顛倒。與樹相似,二叉樹也以遞歸的形式定義。二叉樹是n (n >=0) 個結點的有限集合:
1)或者為空二叉樹,即n=0 。
2)或者由一個根結點和兩個互不相交的被稱為根的左子樹和右子樹組成。左子樹和右子樹又分別是一棵二叉樹。二叉樹是有序樹,若將其左、右子樹顛倒,則成為另一棵不同的二叉樹。即使樹中結點只有
一棵子樹,也要區分它是左子樹還是右子樹滿二叉樹:滿二叉樹是指除了最后一層外其他節點均有兩顆子樹。
完全二叉樹:完全二叉樹是指除了最后一層外,其他任何一層的節點數均達到最大值,且最后一層也只是在最右側缺少節點
二叉樹的存儲:二叉樹可以用鏈式存儲結構來存儲,滿二叉樹和完全二叉樹可以用順序存儲結構來存儲
二叉樹的遍歷:二叉樹有先序遍歷(根左右),中序遍歷(左根右)和后續遍歷(左右根);還有層次遍歷,需要借助一個隊列。
三種遍歷算法中,遞歸遍歷左、右子樹的順序都是固定的,只是訪問根結點的順序不同。不管采用哪種遍歷算法,每個結點都訪問一次且僅訪問一次,故時間復雜度都是O(n) 。在遞歸遍歷
中,遞歸工作棧的棧深恰好為樹的深度,所以在最壞情況下,二叉樹是有n 個結點且深度為n 的單支樹,遍歷算法的空間復雜度為O(n) 。
20.如何由遍歷序列構造一棵二叉樹?
1)由二叉樹的先序序列和中序序列可以唯一地確定一棵二叉樹。
在先序遍歷序列中,第一個結點一定是二叉樹的根結點;而在中序遍歷中,根結點必然將中
序序列分割成兩個子序列,前一個子序列是根結點的左子樹的中序序列,后一個子序列是根結點的右子樹的中序序列。根據這兩個子序列,在先序序列中找到對應的左子序列和右子序列。在先序序列中,左子序列的第一個結點是左子樹的根結點,右子序列的第一個結點是右子樹的根結點。如此遞歸地進行下去,便能唯一地確定這棵二叉樹。2)由二叉樹的后序序列和中序序列也可以唯一地確定一棵二叉樹。
因為后序序列的最后一個結點就如同先序序列的第一個結點,可以將中序序列分割成兩個子
序列,然后采用類似的方法遞歸地進行划分,進而得到一棵二叉樹。3)由二叉樹的層序序列和中序序列也可以唯一地確定一棵二叉樹。需要注意的是,若只知道二叉樹的先序序列和后序序列,則無法唯一確定一棵二叉樹。
21.線索二叉樹的概念?
對於n個結點的二叉樹,在二叉鏈存儲結構中有n+1個空鏈域,利用這些空鏈域存放在某種遍歷次序下該結點的前驅結點和后繼結點的指針,這些指針稱為線索,加上線索的二叉樹稱為線索二叉樹。
這種加上了線索的二叉鏈表稱為線索鏈表,相應的二叉樹稱為線索二叉樹(Threaded BinaryTree)。根據線索性質的不同,線索二叉樹可分為前序線索二叉樹、中序線索二叉樹和后序線索二叉樹三種。
**注意:**線索鏈表解決了無法直接找到該結點在某種遍歷序列中的前驅和后繼結點的問題,解決了二叉鏈表找左、右孩子困難的問題。
二叉樹的遍歷本質上是將一個復雜的非線性結構轉換為線性結構,使每個結點都有了唯一前驅和后繼(第一個結點無前驅,最后一個結點無后繼)。對於二叉樹的一個結點,查找其左右子女是方便的,其前驅后繼只有在遍歷中得到。為了容易找到前驅和后繼,有兩種方法。一是在結點結構中增加向前和向后的指針,這種方法增加了存儲開銷,不可取;二是利用二叉樹的空鏈指針。
22.樹的存儲結構?
1.雙親表示法:
這種存儲方式采用一組連續空間來存儲每個結點,同時在每個結點中增設一個偽指針,指示
其雙親結點在數組中的位置。
該存儲結構利用了每個結點(根結點除外)只有唯一雙親的性質,可以很快得到每個結點的
雙親結點,但求結點的孩子時需要遍歷整個結構。
2.孩子表示法:
孩子表示法是將每個結點的孩子結點都用單鏈表鏈接起來形成一個線性結構,此時n 個結點
就有n 個孩子鏈表(葉子結點的孩子鏈表為空表),這種存儲方式尋找子女的操作非常直接,而尋找雙親的操作需要遍歷n個結點中孩子鏈表指針域所指向的n個孩子鏈表。
3.孩子兄弟表示法:
孩子兄弟表示法又稱二叉樹表示法,即以二叉鏈表作為樹的存儲結構。孩子兄弟表示法使每
個結點包括三部分內容:結點值、指向結點第一個孩子結點的指針,及指向結點下一個兄弟結點的指針(沿此域可以找到結點的所有兄弟結點)
這種存儲表示法比較靈活,其最大的優點是可以方便地實現樹轉換為二叉樹的操作,易於查
找結點的孩子等,但缺點是從當前結點查找其雙親結點比較麻煩。若為每個結點增設一個parent域指向其父結點,則查找結點的父結點也很方便。
23.二叉排序樹
1.二叉排序樹的定義:
二叉排序樹(也稱二叉查找樹)或者是一棵空樹,或者是具有下列特性的二叉樹:
- 若左子樹非空,則左子樹上所有結點的值均小於根結點的值。
- 若右子樹非空,則右子樹上所有結點的值均大於根結點的值。
- 左、右子樹也分別是一棵二叉排序樹。
根據二叉排序樹的定義,左子樹結點值<根結點值<右子樹結點值,所以對二叉排序樹進行中序遍歷,可以得到一個遞增的有序序列。2.二叉排序樹的查找:
二叉排序樹的查找是從根節點開始的,延某個分支逐層向下比較的過程。若二叉樹非空,先將給定值與根結點的關鍵字比較,若相等,則查找成功;若不等,如果小於根結點的關鍵字,則在根結點的左子樹上查找,否則在根的右子樹上查找。這顯然是一個遞歸的過程。
24.平衡二叉樹
為避免樹的高度增長過快,降低二叉排序樹的性能,規定在插入和刪除二叉樹結點時,要保證任意結點的左、右子樹高度差的絕對值不超過1, 將這樣的二叉樹稱為平衡二叉樹(Balanced Binary Tree), 簡稱平衡樹。定義結點左子樹與右子樹的高度差為該結點的平衡因子,則平衡二叉樹結點的平衡因子的值只可能是-1 、0 或1 。因此,平衡二叉樹可定義為或者是一棵空
樹,或者是具有下列性質的二叉樹:它的左子樹和右子樹都是平衡二叉樹,且左子樹和右子
樹的高度差的絕對值不超過1 。
25.哈夫曼樹和哈夫曼編碼:
2.哈夫曼樹的構造
給定n 個權值分別為W1,W2…, Wn 的結點,構造哈夫曼樹的算法描述如下:
- 將這n 個結點分別作為n 棵僅含一個結點的二叉樹,構成森林F 。
- 構造一個新結點,從F 中選取兩棵根結點權值最小的樹作為新結點的左、右子樹,並且將新結點的權值置為左、右子樹上根結點的權值之和。
- 從F 中刪除剛才選出的兩棵樹,同時將新得到的樹加入F 中。
- 重復步驟2) 和3)'直至F 中只剩下一棵樹為止。
從上述構造過程中可以看出哈夫曼樹具有如下特點:
- 每個初始結點最終都成為葉結點,且權值越小的結點到根結點的路徑長度越大。
- 構造過程中共新建了n — 1 個結點(雙分支結點),因此哈夫曼樹的結點總數為2n -1 。
- 每次構造都選擇2 棵樹作為新結點的孩子,因此哈夫曼樹中不存在度為1 的結點。
3.哈夫曼編碼:
在數據通信中,若對每個字符用相等長度的二進制位表示,稱這種編碼方式為固定長度編碼。
若允許對不同字符用不等長的二進制位表示,則這種編碼方式稱為可變長度編碼。可變長度編碼比固定長度編碼要好得多,其特點是對頻率高的字符賦以短編碼,而對頻率較低的字符則賦以較長一些的編碼,從而可以使字符的平均編碼長度減短,起到壓縮數據的效果。哈夫曼編碼是一種被廣泛應用而且非常有效的數據壓縮編碼。若沒有一個編碼是另一個編碼的前綴,則稱這樣的編碼為前綴編碼。由哈夫曼樹得到哈夫曼編碼是很自然的過程。首先,將每個出現的字符當作一個獨立的結點,
其權值為它出現的頻度(或次數),構造出對應的哈夫曼樹。顯然,所有字符結點都出現在葉結點中。我們可將字符的編碼解釋為從根至該字符的路徑上邊標記的序列,其中邊標記為0 表示“轉向左孩子”,標記為1 表示“轉向右孩子“。
快速喚起記憶知識框架:
26.圖的一些相關定義
這個比較基礎,忘了的自己去看看把,學過離散的應該比較熟悉。
27.圖的存儲結構:
1.鄰接矩陣法:
所謂鄰接矩陣存儲,是指用一個一維數組存儲圖中頂點的信息,用一個二維數組存儲圖中邊
的信息(即各頂點之間的鄰接關系),存儲頂點之間鄰接關系的二維數組稱為鄰接矩陣。有向圖、無向圖和網對應的鄰接矩陣實例圖如下:
適合稠密圖。
2.鄰接表法:
當一個圖為稀疏圖時,使用鄰接矩陣法顯然要浪費大量的存儲空間,而圖的鄰接表法結合了
順序存儲和鏈式存儲方法,大大減少了這種不必要的浪費。所謂鄰接表,是指對圖G 中的每個頂點V建立一個單鏈表,第i個單鏈表中的結點表示依附於頂點v, 的邊(對於有向圖則是以頂點v, 為尾的弧),這個單鏈表就稱為頂點vi 的邊表(對於有向圖則稱為出邊表)。邊表的頭指針和頂點的數據信息采用順序存儲(稱為頂點表),所以在鄰接表中存在兩種結點:頂點表結點和邊表結點。
3.十字鏈表法:
十字鏈表法是有向圖的一種鏈式存儲結構。在十字鏈表中,對應於有向圖中的每條弧有一個結點,對應於每個頂點也有一個結點。
4.鄰接多重表:
鄰接多重表是無向圖的另一種鏈式存儲結構。
在鄰接表中,容易求得頂點和邊的各種信息,但在鄰接表中求兩個頂點之間是否存在邊而對
邊執行刪除等操作時,需要分別在兩個頂點的邊表中遍歷,效率較低。與十字鏈表類似,在鄰接多重表中,每條邊用一個結點表示,每個頂點也用一個結點表示。
28.圖的遍歷(代碼請自己寫)
圖的遍歷是指從圖中的某一頂點出發,按照某種搜索方法沿着圖中的邊對圖中的所有頂點訪
問一次且僅訪問一次。注意到樹是一種特殊的圖,所以樹的遍歷實際上也可視為一種特殊的圖的遍歷。圖的遍歷算法是求解圖的連通性問題、拓撲排序和求關鍵路徑等算法的基礎。圖的遍歷比樹的遍歷要復雜得多,因為圖的任一頂點都可能和其余的頂點相鄰接,所以在訪問某個頂點后,可能沿着某條路徑搜索又回到該頂點上。為避免同一頂點被訪問多次,在遍歷圖的過程中,必須記下每個已訪問過的頂點,為此可以設一個輔助數組visited[] 來標記頂點是否被訪問過。圖的遍歷算法主要有兩種:廣度優先搜索和深度優先搜索。1.廣度優先搜索(Breadth-First-Search, BFS):
類似於二叉樹的層序遍歷算法。基本思想是:首先訪問起始頂點V, 接着由V出發,依次訪問V 的各個未訪問過的鄰接頂點W1, W2,… Wn, 然后依次訪問W1, W2,…, Wn 的所有未被訪問過的鄰接頂點;再從這些訪問過的頂點出發,訪問它們所有未被訪問過的鄰接頂點,直至圖中所有頂點都被訪問過為止。若此時圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作為初始點,重復上述過程。Dijkstra源最短路徑算法和Prim 最小生成樹算法也應用了類似的思想。
2.深度優先搜索(Depth-First-Search, DFS):
它的基本思想如下:首先訪問圖中某一起始頂點V, 然后由v 出發,訪問與v 鄰接且未被訪問的任一頂點W1, 再訪問與W1鄰接且未被訪問的任一頂點W2……重復上述過程。當不能再繼續向下訪問時,依次退回到最近被訪問的頂點,若它還有鄰接頂點未被訪問過,則從該點開始繼續上述搜索過程,直至圖中所有頂點均被訪問過為止。
29.最小生成樹和最短路徑:
這四個算法請自己去翻書或百度,這是圖的比較經典的應用。
迪傑斯特拉(dijkstra)算法:迪傑斯特拉算法是經典的單源最短路徑算法,用於求某一頂點到其他頂點的最短路徑,它的特點是以起始點為中心層層向外擴展,直到擴展的終點為止,迪傑斯特拉算法要求邊的權值不能為負權。
弗洛伊德(Floyd)算法:弗洛伊德算法是經典的求任意頂點之間的最短路徑,其邊的權值可為負權,該算法的時間復雜度為O(N3),空間復雜度為O(N2)。
普里姆(prim)算法:用來求最小生成樹,其基本思想為:從聯通網絡N={V,E}中某一頂點u0出發,選擇與他關聯的最小權值的邊,將其頂點加入到頂點集S中,此后就從一個頂點在S集中,另一個頂點不在S集中的所有頂點中選擇出權值最小的邊,把對應頂點加入到S集中,直到所有的頂點都加入到S集中為止。
克魯斯卡爾(kruskal)算法:用來求最小生成樹,其基本思想為:設有一個有N個頂點的聯通網絡N={V,E},初試時建立一個只有N個頂點,沒有邊的非連通圖T,T中每個頂點都看作是一個聯通分支,從邊集E中選擇出權值最小的邊且該邊的兩個端點不在一個聯通分支中,則把該邊加入到T中,否則就再從新選擇一條權值最小的邊,直到所有的頂點都在一個聯通分支中為止。
30.關鍵路徑:
AOE和AOV偏理解以及手動模擬,也自己去看吧。
快速喚起記憶知識框架:
31.對各種查找方法的概括?
查找分為靜態查找表和動態查找表;靜態查找表包括:順序查找、折半查找、分塊查找;動態查找包括:二叉排序樹和平衡二叉樹。
(1)順序查找:把待查關鍵字key放入哨兵位置(i=0),再從后往前依次把表中元素和key比較,如果返回值為0則查找失敗,表中沒有這個key值,如果返回值為元素的位置i(i!=0)則查找成功,設置哨兵的位置是為了加快執行速度。他的時間效率為O(n),其特點是:結構簡單,對順序結構和連式結構都適用,但是查找效率太低。
(2)折半查找:要求查找表為順序存儲結構並且有序,若關鍵字在表中則返回關鍵字的位置,若關鍵字不在表中時停止查找的典型標志是:查找范圍的上界<=查找范圍的下界。
(3)分塊查找:先把查找表分為若干子表,要求每個子表的元素都要比他后面的子表的元素小,也就是保證塊間是有序的(但是子表內不一定有序),把各子表中的最大關鍵字構成一張索引表,表中還包含各子表的起始地址。他的特點是:塊間有序,塊內無序,查找時塊間進行索引查找,塊內進行順序查找。
(4)二叉排序樹:二叉排序樹的定義為:或者是一棵空樹,或者是一棵具有如下特點的樹:如果該樹有左子樹,則其左子樹的所有節點值小於根的值;若該樹有右子樹,則其右子樹的所有節點值均大於根的值;其左右子樹也分別為二叉排序樹。在查找時可以進行動態的插入,插入節點要符合二叉排序樹的定義,這也是動態查找和靜態查找的區別,靜態查找不能進行動態插入。
(5)平衡二叉樹:平衡二叉樹又稱為AVL樹,它或者是一棵空樹或者具有如下特點:他的左子樹和右子樹的高度差的絕對值不能大於1,且他的左右子樹也都是平衡二叉樹。
平衡因子:是指左子樹的高度減去右子樹的高度,它的值只能為1,0,-1
如果再一個平衡二叉樹中插入一個節點可能造成失衡,這時就要進行樹結構的調整,即平衡旋轉。包括4中情況:在左子樹的左子樹上插入節點時向右進行單向旋轉;在右子樹的右子樹上插入節點時向左進行單向旋轉;在左子樹的右子樹插入節點時先向左旋轉再向右旋轉;在右子樹的左子樹插入節點時先向右旋轉再向左旋轉。
32.B樹和B+樹:
1.B 樹,又稱多路平衡查找樹, B 樹中所有結點的孩子個數的最大值稱為B 樹的階,通常用m
表示。一棵m 階B 樹或為空樹,或為滿足如下特性的m 叉樹:
- 樹中每個結點至多有m 棵子樹,即至多含有m-1 個關鍵字。
- 若根結點不是終端結點,則至少有兩棵子樹。
- 除根結點外的所有非葉結點至少有「m/2] 棵子樹,即至少含有「m/2]- 1 個關鍵字。
- 所有的葉結點都出現在同一層次上,並且不帶信息(可以視為外部結點或類似千折半查找判定樹的查找失敗結點,實際上這些結點不存在,指向這些結點的指針為空)。
B 樹是所有結點的平衡因子均等於0 的多路平衡查找樹。
2.B+樹是應數據庫所需而出現的一種B 樹的變形樹。
一棵m 階的B+樹需滿足下列條件:
- 每個分支結點最多有m 棵子樹(孩子結點)。
- 非葉根結點至少有兩棵子樹,其他每個分支結點至少有「m/2]棵子樹。
- 結點的子樹個數與關鍵字個數相等。
- 所有葉結點包含全部關鍵字及指向相應記錄的指針,葉結點中將關鍵字按大小順序排列,
並且相鄰葉結點按大小順序相互鏈接起來。- 所有分支結點(可視為索引的索引)中僅包含它的各個子結點(即下一級的索引塊)中
關鍵字的最大值及指向其子結點的指針。
m 階的B+樹與m 階的B 樹的主要差異如下:
- 在B+樹中,具有n 個關鍵字的結點只含有n 棵子樹,即每個關鍵字對應一棵子樹;而在
B 樹中,具有n 個關鍵字的結點含有n+1棵子樹。- 在B+樹中,每個結點(非根內部結點)的關鍵字個數n 的范圍是「m/2]<=n<= m (根結點:
1<=n<=m); 在B 樹中,每個結點(非根內部結點)的關鍵字個數n 的范圍是「m/2]-1<=n<=
m-1 。- 在B+樹中,葉結點包含信息,所有非葉結點僅起索引作用,非葉結點中的每個索引項只
含有對應子樹的最大關鍵字和指向該子樹的指針,不含有該關鍵字對應記錄的存儲地址。- 在B+樹中,葉結點包含了全部關鍵字,即在非葉結點中出現的關鍵字也會出現在葉結點
中;而在B 樹中,葉結點包含的關鍵字和其他結點包含的關鍵字是不重復的。
32.哈希表的概念、哈希函數的構造方法、哈希沖突的解決辦法?
哈希表又稱為散列表,是根據關鍵字碼的值直接進行訪問的數據結構,即它通過把關鍵碼的值映射到表中的一個位置以加快查找速度,其中映射函數叫做散列函數,存放記錄的數組叫做散列表。
哈希函數的構造方法包括:直接定址法,除留余數法,數字分析法,平方取中法,折疊法,隨機數法
(1)直接定址法:取關鍵字的某個線性函數值作為散列地址,H(key)=a*key+b。
(2)除留余數法:取關鍵字對p取余的值作為散列地址,其中p<m,即H(key)=key%p (p<m)。
(3)數字分析法:當關鍵字的位數大於地址的位數,對關鍵字的各位分布進行分析,選出分布均勻的任意幾位作為散列的地址,適用於所有關鍵字都已知的情況。
(4)平方取中法:對關鍵字求平方,再取結果中的中間幾位作為散列地址。
(5)折疊法:將關鍵字分為位數相同的幾部分,然后取這幾部分的疊加和作為散列地址。適用於關鍵字位數較多,且關鍵字中每一位上數字分布大致均勻。
(6)隨機數法:選擇一個隨機函數,把關鍵字的隨機函數值作為散列地址。適合於關鍵字的長度不相同時。
哈希沖突的解決方法包括:開放定址法和拉鏈法,當沖突發生時,使用某種探測技術形成一個探測序列,然后沿此序列逐個單單元查找,直到找到該關鍵字或者碰到一個開放的地址為止,探測到開放的地址表明該表中沒有此關鍵字,若要插入,則探測到開放地址時可將新節點插入該地址單元。其中開放定址法包括:線性探查法,二次探查法,雙重散列法
(1)線性探查法:基本思想,探查時從地址d開始,首先探查T[d],在探查T[d+1]…直到查到T[m-1],此后循環到T[0],T[1]…直到探測到T[d-1]為止。
(2)二次探查法:基本思想,探查時從地址d開始,首先探查T[d],再探查T[d+12],T[d+22]…等,直到探查到有空余地址或者探查到T[d-1]為止,缺點是無法探查到整個散列空間。
(3)雙重散列法:基本思想,使用兩個散列函數來確定地址,探查時從地址d開始,首先探查T[d],再探查T[d+h1(d)],T[d+2*h1(d)]…
鏈接法:將所有關鍵字為同義詞的節點鏈接在同一個單鏈表中,若選定的散列表長度為m,則可將散列表定義為一個由m個頭指針組成的指針數組,凡是散列地址為i的節點均插入到頭指針為i的單鏈表中。
快速喚起記憶知識框架:
33.對各種內部排序的概括與總結?
排序:是指把一個任意元素的序列排列成一個按關鍵字key有序的序列。內部排序包括:插入排序、選擇排序、交換排序、歸並排序、基數排序。其中插入排序包括:直接插入排序、折半插入排序、希爾排序;選擇排序包括:簡單選擇排序,堆排序;交換排序包括:冒泡排序、快速排序。
(1)直接插入排序(穩定):基本思想為:將序列分為有序部分和無序部分,從無序部分依次選擇元素與有序部分比較找到合適的位置,將原來的元素往后移,將元素插入到相應位置上。時間復雜度為:O(n^2),空間復雜度為O(1)
(2)折半插入排序(穩定):基本思想為:設置三個變量low high mid,令mid=(low+high)/2,若a[mid]>key,則令high=mid-1,否則令low=mid+1,直到low>high時停止循環,對序列中的每個元素做以上處理,找到合適位置將其他元素后移進行插入。他的比較次數為O(nlog2n),但是因為要后移,因此時間復雜度為O(n^2),空間復雜度為O(1)。 優點是:比較次數大大減少。
(3)希爾排序(不穩定):基本思想為:先將序列分為若干個子序列,對各子序列進行直接插入排序,等到序列基本有序時再對整個序列進行一次直接插入排序。優點是:讓關鍵字值小的元素能夠很快移動到前面,且序列基本有序時進行直接插入排序時間效率會提升很多,空間復雜度為O(1)。
(4)簡單選擇排序(不穩定):基本思想為:將序列分為2部分,每經過一趟就在無序部分找到一個最小值然后與無序部分的第一個元素交換位置。優點是:實現起來特別簡單,缺點是:每一趟只能確定一個元素的位置,時間效率低。時間復雜度為O(n^2),空間復雜度為O(1)。
(5)堆排序(不穩定):設有一個任意序列,k1,k2,…,kn,當滿足下面特點時稱之為堆:讓此序列排列成完全二叉樹,該樹具有以下特點,該樹中任意節點均大於或小於其左右孩子,此樹的根節點為最大值或者最小值。優點是:對大文件效率明顯提高,但對小文件效率不明顯。時間復雜度為O(nlog2n),空間復雜度為O(1)。
(6)冒泡排序(穩定):基本思路為:每一趟都將元素進行兩兩比較,並且按照“前小后大”的規則進行交換。優點是:每一趟不僅能找到一個最大的元素放到序列后面,而且還把其他元素理順,如果下一趟排序沒有發生交換則可以提前結束排序。時間復雜度為O(n^2),空間復雜度為O(1)。
(7)快速排序(不穩定):基本思路為:在序列中任意選擇一個元素作為中心,比它大的元素一律向后移動,比它小的元素一律向前移動,形成左右兩個子序列,再把子序列按上述操作進行調整,直到所有的子序列中都只有一個元素時序列即為有序。優點是:每一趟不僅能確定一個元素,時間效率較高。時間復雜度為O(nlog2n),空間復雜度為O(log2n).
(8)歸並排序(穩定):基本思想為:把兩個或者兩個以上的有序表合並成一個新的有序表。時間復雜度為O(nlogn),空間復雜度和待排序的元素個數相同。
(9)基數排序:時間復雜度為:對於n個記錄進行鏈式基數排序的時間復雜度為O(d(n+rd)),其中每一趟分配的時間復雜度為O(n),回收的時間復雜度為O(rd)。
各種排序的總結表格如下:
直接插入排序、冒泡排序和簡單選擇排序是基本的排序方法,它們主要用於元素個數n不是很大(n < 10000) 的情形。
對於中等規模的元素序列(n <=1000), 希爾排序是一種很好的選擇。
對於元素個數n 很大的情況,可以采用快排、堆排序、歸並排序或基數排序,其中快排和堆排序都是不穩定的,而歸並排序和基數排序是穩定的排序算法。