數據結構常見面試題

   本意用於考研複試,如下是博主本身整理,博主是大四本科生,不能保證內容徹底正確,請辯證地看,若是有問題能夠在評論區指出我再修改。 整理不易,我就不掛個二維碼請遊客付費了,若是能夠的話,麻煩高擡貴手,點一下右下角的推薦吧! 程序員

一、數組和鏈表的區別。算法

從邏輯結構上來看,數組必須實現定於固定的長度,不能適應數據動態增減的狀況,即數組的大小一旦定義就不能改變。當數據增長是,可能超過原先定義的元素的個數;當數據減小時,形成內存浪費;鏈表動態進行存儲分配,能夠適應數據動態地增減的狀況,且能夠方便地插入、刪除數據項。數組

從內存存儲的角度看;數組從棧中分配空間(用new則在堆上建立),對程序員方便快速,可是自由度小;鏈表從堆中分配空間,自由度大可是申請管理比較麻煩。安全

從訪問方式類看,數組在內存中是連續的存儲,所以能夠利用下標索引進行訪問;鏈表是鏈式存儲結構,在訪問元素時候只可以經過線性方式由前到後順序的訪問,因此訪問效率比數組要低。數據結構

 

 

二、簡述快速排序過程函數

1)選擇一個基準元素,一般選擇第一個元素或者最後一個元素,性能

2)經過一趟排序將待排序的記錄分割成獨立的兩部分,其中一部分記錄的元素值均比基準元素值小。另外一部分記錄的元素值比基準值大。優化

3)此時基準元素在其排好序後的正確位置指針

4)而後分別對這兩部分記錄用一樣的方法繼續進行排序,直到整個序列有序。blog

 

三、快速排序的改進

只對長度大於k的子序列遞歸調用快速排序,讓原序列基本有序,而後再對整個基本有序序列用插入排序算法排序。實踐證實,改進後的算法時間複雜度有所下降,且當k取值爲 8 左右時,改進算法的性能最佳。

選擇基準元的方式

對於分治算法,當每次劃分時,算法若都能分紅兩個等長的子序列時,那麼分治算法效率會達到最大。也就是說,基準的選擇是很重要的。選擇基準的方式決定了兩個分割後兩個子序列的長度,進而對整個算法的效率產生決定性影響。最理想的方法是,選擇的基準剛好能把待排序序列分紅兩個等長的子序列。

  方法1 固定基準元

若是輸入序列是隨機的,處理時間是能夠接受的。若是數組已經有序時,此時的分割就是一個很是很差的分割。

方法2 隨機基準元

這是一種相對安全的策略。因爲基準元的位置是隨機的,那麼產生的分割也不會老是會出現劣質的分割。在整個數組數字全相等時,仍然是最壞狀況,時間複雜度是O(n^2)。實際上,隨機化快速排序獲得理論最壞狀況的可能性僅爲1/(2^n)。因此隨機化快速排序能夠對於絕大多數輸入數據達到O(nlogn)的指望時間複雜度。

方法3 三數取中

引入的緣由:雖然隨機選取基準時,減小出現很差分割的概率,可是仍是最壞狀況下仍是O(n^2),要緩解這種狀況,就引入了三數取中選取基準。

分析:最佳的劃分是將待排序的序列分紅等長的子序列,最佳的狀態咱們可使用序列的中間的值,也就是第N/2個數。但是,這很難算出來,而且會明顯減慢快速排序的速度。這樣的中值的估計能夠經過隨機選取三個元素並用它們的中值做爲基準元而獲得。事實上,隨機性並無多大的幫助,所以通常的作法是使用左端、右端和中心位置上的三個元素的中值做爲基準元。

4、各種排序算法對比

 

 

時間複雜度來講:

(1)平方階(O(n2))排序
  各種簡單排序:直接插入、直接選擇和冒泡排序;
 (2)線性對數階(O(nlog2n))排序
  快速排序、堆排序和歸併排序;
 (3)O(n1+§))排序,§是介於0和1之間的常數。

       希爾排序
(4)線性階(O(n))排序
  基數排序,此外還有桶、箱排序。

說明:

當原表有序或基本有序時,直接插入排序和冒泡排序將大大減小比較次數和移動記錄的次數,時間複雜度可降至O(n);

而快速排序則相反,當原表基本有序時,將蛻化爲冒泡排序,時間複雜度提升爲O(n2);

原表是否有序,對簡單選擇排序、堆排序、歸併排序和基數排序的時間複雜度影響不大。

 

穩定性:

排序算法的穩定性:若待排序的序列中,存在多個具備相同關鍵字的記錄,通過排序,這些記錄的相對次序保持不變,則稱該算法是穩定的;若經排序後,記錄的相對次序發生了改變,則稱該算法是不穩定的。 

穩定的排序算法:冒泡排序、插入排序、歸併排序和基數排序

不是穩定的排序算法:選擇排序、快速排序、希爾排序、堆排序

 

選擇排序算法準則:

通常而言,須要考慮的因素有如下四點:

設待排序元素的個數爲n.

1)當n較大,則應採用時間複雜度爲O(nlog2n)的排序方法:快速排序、堆排序或歸併排序序。

2)當n較大,內存空間容許,且要求穩定性:歸併排序

3)當n較小,可採用直接插入或直接選擇排序。

    直接插入排序:當元素分佈有序,直接插入排序將大大減小比較次數和移動記錄的次數。

    直接選擇排序 :元素分佈有序,若是不要求穩定性,選擇直接選擇排序

5)通常不使用或不直接使用傳統的冒泡排序。

6基數排序
它是一種穩定的排序算法,但有必定的侷限性:
  一、關鍵字可分解。
  二、記錄的關鍵字位數較少,若是密集更好
  三、若是是數字時,最好是無符號的

 

 

五、冒泡排序算法的改進

1.設置一標誌性變量pos,用於記錄每趟排序中最後一次進行交換的位置。因爲pos位置以後的記錄均已交換到位,故在進行下一趟排序時只要掃描到pos位置便可。

2.傳統冒泡排序中每一趟排序操做只能找到一個最大值或最小值,咱們考慮利用在每趟排序中進行正向和反向兩遍冒泡的方法一次能夠獲得兩個最終值(最大者和最小者) , 從而使排序趟數幾乎減小了一半。

 

六、鄰接矩陣與鄰接表

鄰接矩陣表示法:在一個一維數組中存儲全部的點,在一個二維數組中存儲頂點之間的邊的權值

鄰接表表示法:圖中頂點用一個一維數組存儲,圖中每一個頂點vi的全部鄰接點構成單鏈表

對比

1)在鄰接矩陣表示中,無向圖的鄰接矩陣是對稱的。矩陣中第 i 行或 第 i 列有效元素個數之和就是頂點的度。

在有向圖中 第 i 行有效元素個數之和是頂點的出度,第 i 列有效元素個數之和是頂點的入度。

2)在鄰接表的表示中,無向圖的同一條邊在鄰接表中存儲的兩次。若是想要知道頂點的度,只須要求出所對應鏈表的結點個數便可。

有向圖中每條邊在鄰接表中只出現一次,求頂點的出度只須要遍歷所對應鏈表便可。求入度則須要遍歷其餘頂點的鏈表。

3)鄰接矩陣與鄰接表優缺點:

鄰接矩陣的優勢是能夠快速判斷兩個頂點之間是否存在邊,能夠快速添加邊或者刪除邊。而其缺點是若是頂點之間的邊比較少,會比較浪費空間。由於是一個 n∗n 的矩陣。

而鄰接表的優勢是節省空間,只存儲實際存在的邊。其缺點是關注頂點的度時,就可能須要遍歷一個鏈表。

 

 

7.用循環比遞歸效率高嗎?

遞歸和循環二者徹底能夠互換。不能徹底決定性地說循環地效率比遞歸的效率高。

2.1遞歸算法:

優勢:代碼簡潔、清晰,而且容易驗證正確性。

缺點:它的運行須要較屢次數的函數調用,若是調用層數比較深,須要增長額外的堆棧處理(還有可能出現堆棧溢出的狀況),好比參數傳遞須要壓棧等操做,會對執行效率有必定影響。可是,對於某些問題,若是不使用遞歸,那將是極端難看的代碼。在編譯器優化後,對於屢次調用的函數處理會有很是好的效率優化,效率未必低於循環。

2.2循環算法:

優勢:速度快,結構簡單。

缺點:並不能解決全部的問題。有的問題適合使用遞歸而不是循環。若是使用循環並不困難的話,最好使用循環。

 

八、解決哈希衝突的方法

哈希表(Hash table,也叫散列表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。

1) 線性探測法

2) 平方探測法

3) 僞隨機序列法

4) 拉鍊法

 

九、KMP算法:在一個字符串中查找是否包含目標的匹配字符串。其主要思想是每趟比較過程讓子串前後滑動一個合適的位置。當發生不匹配的狀況時,不是右移一位,而是移動(當前匹配的長度– 當前匹配子串的部分匹配值)位。

 

十、B樹

根據B類樹的特色,構造一個多階的B類樹,而後在儘可能多的在結點上存儲相關的信息,保證層數儘可能的少,以便後面咱們能夠更快的找到信息,磁盤的I/O操做也少一些,並且B類樹是平衡樹,每一個結點到葉子結點的高度都是相同,這也保證了每一個查詢是穩定的。

B樹和B+樹的區別,以一個m階樹爲例。

  1. 關鍵字的數量不一樣;B+樹中分支結點有m個關鍵字,其葉子結點也有m個,其關鍵字只是起到了一個索引的做用,可是B樹雖然也有m個子結點,可是其只擁有m-1個關鍵字。
  2. 存儲的位置不一樣;B+樹中的數據都存儲在葉子結點上,也就是其全部葉子結點的數據組合起來就是完整的數據,可是B樹的數據存儲在每個結點中,並不只僅存儲在葉子結點上。
  3. 分支結點的構造不一樣;B+樹的分支結點僅僅存儲着關鍵字信息和兒子的指針(這裏的指針指的是磁盤塊的偏移量),也就是說內部結點僅僅包含着索引信息。
  4. 查詢不一樣;B樹在找到具體的數值之後,則結束,而B+樹則須要經過索引找到葉子結點中的數據才結束,也就是說B+樹的搜索過程當中走了一條從根結點到葉子結點的路徑。
相關文章
相關標籤/搜索