計算機考研復試面試常問問題 數據結構篇(上)
使用前需知(拒絕白嫖,如果對你有幫助,你只需點個贊就行):
需要pdf直接打印版,可在公眾號"程序員寶藏"回復復試上岸獲取(會持續更新)

在復習過程中,我用心查閱並整理了在考研復試面試中可能問到的大部分問題,並分點整理了答案,可以直接理解背誦並加上自己的語言潤色!極力推薦打印下來看,效率更高!
聲明:一些邊邊角角的沒有收集,畢竟是考研面試,不是筆試,這樣也能減輕大家的負擔!
此系列一共有8篇:編程語言篇**|數據結構篇|操作系統篇|組成原理篇|計算機網絡篇|數據庫篇|軟件工程篇|計算機專業英語篇**(還未全部完成,敬請期待,你們的支持和關注是我最大的動力!)
個人整理,不可用於商業用途,轉載請注明出處。
需要408電子書2021版,可在公眾號"程序員寶藏"回復408電子書獲取
需要408初試視頻2021版,可在公眾號"程序員寶藏"回復408視頻獲取
需要復試機試視頻,可在公眾號"程序員寶藏"回復機試必過獲取
加油,大家都可以上岸!!!讓我們一起努力!!!
第一章、緒論
快速喚起記憶知識框架:
1 .時間復雜度
ps:我看到一個學長回憶說老師問了他 大O 是什么意思???如果是我,估計當場蒙蔽了,畢竟平時知道做題就行,也沒仔細看 大O 什么意思,所以大家還是看看這題。有備無患。
一個語句的頻度是指該語句在算法中被重復執行的次數。算法中所有語句的頻度之和記為T(n), 它是該算法問題規模n 的函數,時間復雜度主要分析T(n) 的數量級。算法中基本運算(最深層循環內的語句)的頻度與T(n) 同數量級,因此通常采用算法中基本運算的頻度f(n)來分析算法的時間復雜度。因此,算法的時間復雜度記為 T(n) = O(f(n))
取f(n) 中隨n 增長最快的項,將其系數置為1 作為時間復雜度的度量。例如, f(n) = an^3^ + bn^2^ + cn 的時向復雜度為O(n^3^)
上式中, O 的含義是T(n) 的數量級,其嚴格的數學定義是:若T(n)和f(n)是定義在正整數集合上的兩個函數,則存在正常數C 和n~0~,使得當n >= n~0~時,都滿足0 <=T(n) <=Cf(n) 。 算法的時間復雜度不僅依賴於問題的規模n, 也取決於待輸入數據的性質(如輸入數據元素 的初始狀態)
2.空間復雜度
算法的空間復雜度S(n)定義為該算法所耗費的存儲空間,它是問題規模n 的函數。記為 S(n) = O(g(n)) 一個程序在執行時除需要存儲空間來存放本身所用的指令、常數、變量和輸入數據外,還需要一些對數據進行操作的工作單元和存儲一些為實現計算所需信息的輔助空間。若輸入數據所占空間只取決於問題本身,和算法無關,則只需分析除輸入和程序之外的額外空間。 算法原地工作是指算法所需的輔助空間為常量,即O(1) 。
3.數的邏輯結構
指的是數據元素之間邏輯關系,與數的存儲結構無關,是獨立於計算機的,以下是分類圖。
4.數的存儲結構
存儲結構是指數據結構在計算機中的表示,也稱物理結構,主要有以下4種:
順序存儲。把邏輯上相鄰的元素存儲在物理位置上也相鄰的存儲單元中,元素之間的關系由存儲單元的鄰接關系來體現。其優點是可以實現隨機存取,每個元素占用最少的存儲空間;缺點是只能使用相鄰的一整塊存儲單元,因此可能產生較多的外部碎片。
鏈式存儲。不要求邏輯上相鄰的元素在物理位置上也相鄰,借助指示元素存儲地址的指針來表示元素之間的邏輯關系。其優點是不會出現碎片現象,能充分利用所有存儲單元;缺點是每個元素因存儲指針而占用額外的存儲空間,且只能實現順序存取。
索引存儲。在存儲元素信息的同時,還建立附加的索引表。索引表中的每項稱為索引項,索引項的一般形式是(關鍵字,地址)。其優點是檢索速度快;缺點是附加的索引表額外占用存儲空間。另外,增加和刪除數據時也要修改索引表,因而會花費較多的時間。
散列存儲。根據元素的關鍵字直接計算出該元素的存儲地址,又稱哈希(Hash) 存儲。其優點是檢索、增加和刪除結點的操作都很快;缺點是若散列函數不好,則可能出現元素存儲單元的沖突,而解決沖突會增加時間和空間開銷。
5.用循環比遞歸的效率高嗎?
循環和遞歸兩者是可以互換的,不能決定性的說循環的效率比遞歸高。
遞歸的優點是:代碼簡潔清晰,容易檢查正確性;缺點是:當遞歸調用的次數較多時,要增加額外的堆棧處理,有可能產生堆棧溢出的情況,對執行效率有一定的影響。
循環的優點是:結構簡單,速度快;缺點是:它並不能解決全部問題,有的問題適合於用遞歸來解決不適合用循環。
6.貪心算法和動態規划以及分治法的區別?
貪心算法顧名思義就是做出在當前看來是最好的結果,它不從整體上加以考慮,也就是局部最優解。貪心算法從上往下,從頂部一步一步最優,得到最后的結果,它不能保證全局最優解,與貪心策略的選擇有關。
動態規划是把問題分解成子問題,這些子問題可能有重復,可以記錄下前面子問題的結果防止重復計算。動態規划解決子問題,前一個子問題的解對后一個子問題產生一定的影響。在求解子問題的過程中保留哪些有可能得到最優的局部解,丟棄其他局部解,直到解決最后一個問題時也就是初始問題的解。動態規划是從下到上,一步一步找到全局最優解。(各子問題重疊)
分治法(divide-and-conquer):將原問題划分成n個規模較小而結構與原問題相似的子問題;遞歸地解決這些子問題,然后再合並其結果,就得到原問題的解。(各子問題獨立)
分治模式在每一層遞歸上都有三個步驟:
分解(Divide):將原問題分解成一系列子問題; 解決(conquer):遞歸地解各個子問題。若子問題足夠小,則直接求解; 合並(Combine):將子問題的結果合並成原問題的解。
例如歸並排序。
第二章、線性表
快速喚起記憶知識框架:
7.順序表和鏈表的比較
1.存取(讀寫)方式 順序表可以順序存取,也可以隨機存取,鏈表只能從表頭順序存取元素。例如在第i個位置上執行存或取的操作,順序表僅需一次訪問,而鏈表則需從表頭開始依次訪問i次。
2.邏輯結構與物理結構 采用順序存儲時,邏輯上相鄰的元素,對應的物理存儲位置也相鄰。而采用鏈式存儲時,邏輯上相鄰的元素,物理存儲位置則不一定相鄰,對應的邏輯關系是通過指針鏈接來表示的。
3.查找、插入和刪除操作 對於按值查找,順序表無序時,兩者的時間復雜度均為O(n); 順序表有序時,可采用折半查找,此時的時間復雜度為O(log2n) 。
對於按序號查找,順序表支持隨機訪問,時間復雜度僅為0(1), 而鏈表的平均時間復雜度為O(n) 。順序表的插入、刪除操作,平均需要移動半個表長的元素。鏈表的插入、刪除操作,只需修改相關結點的指針域即可。由於鏈表的每個結點都帶有指針域,故而存儲密度不夠大。
4.空間分配 順序存儲在靜態存儲分配情形下,一旦存儲空間裝滿就不能擴充,若再加入新元素,則會出現內存溢出,因此需要預先分配足夠大的存儲空間。預先分配過大,可能會導致順序表后部大量閑置;預先分配過小,又會造成溢出。動態存儲分配雖然存儲空間可以擴充,但需要移動大量元素,導致操作效率降低,而且若內存中沒有更大塊的連續存儲空間,則會導致分配失敗。鏈式存儲的結點空間只在需要時申請分配,只要內存有空間就可以分配,操作靈活、高效。
8.頭指針和頭結點的區別?
頭指針:是指向第一個節點存儲位置的指針,具有標識作用,頭指針是鏈表的必要元素,無論鏈表是否為空,頭指針都存在。
頭結點:是放在第一個元素節點之前,便於在第一個元素節點之前進行插入和刪除的操作,頭結點不是鏈表的必須元素,可有可無,頭結點的數據域也可以不存儲任何信息。
第三章、棧和隊列
快速喚起記憶知識框架:
9.棧和隊列的區別?
隊列是允許在一段進行插入另一端進行刪除的線性表。隊列顧名思義就像排隊一樣,對於進入隊列的元素按“先進先出”的規則處理,在表頭進行刪除在表尾進行插入。由於隊列要進行頻繁的插入和刪除,一般為了高效,選擇用定長數組來存儲隊列元素,在對隊列進行操作之前要判斷隊列是否為空或是否已滿。如果想要動態長度也可以用鏈表來存儲隊列,這時要記住隊頭和對位指針的地址。
棧是只能在表尾進行插入和刪除操作的線性表。對於插入到棧的元素按“后進先出”的規則處理,插入和刪除操作都在棧頂進行,與隊列類似一般用定長數組存儲棧元素。由於進棧和出棧都是在棧頂進行,因此要有一個size變量來記錄當前棧的大小,當進棧時size不能超過數組長度,size+1,出棧時棧不為空,size-1。
10.共享棧
利用棧底位置相對不變的特性,可以讓兩個順序棧共享一個一維數組空間,將兩個棧的棧底分別設置在共享空間的兩端,兩個棧頂向共享空間的中間延伸。這樣能夠更有效的利用存儲空間,兩個棧的空間相互調節,只有在整個存儲空間被占滿時才發生上溢。

11.如何區分循環隊列是隊空還是隊滿?
普通情況下,循環隊列隊空和隊滿的判定條件是一樣的,都是Q.front == Q.rear。
ps:隊頭指針指向第一個數;隊尾指針指向最后一個數的下一個位置,即將要入隊的位置。
方法一:犧牲一個單元來區分隊空和隊滿,這個時候(Q.rear+1)%MaxSize == Q.front才是隊滿標志 。
方法二:類型中增設表示元素個數的數據成員。這樣,隊空的條件為Q.size == 0;隊滿的條件為Q.size == MaxSize。
12.棧在括號匹配中的算法思想?
括號匹配算法思想
(1)出現的凡是“左括號”,則進棧;
(2)出現的是“右括號”,
首先檢查棧是否空?
若棧空,則表明該“右括號”多余
否則和棧頂元素比較?
若相匹配,則棧頂“左括號出棧”
否則表明不匹配
(3)表達式檢驗結束時,
若棧空,則表明表達式中匹配正確
否則表明“左括號”有余;
13.棧在通過后綴表達式求值的算法思想?
順序掃描表達式的每一項,然后根據它的類型做如下相應操作:若該項是操作數,則將其壓入棧中;若該項是操作符,則連續從棧中退出兩個操作數y 和x, 形成運算指令XY, 並將計算結果重新壓入棧中。當表達式的所有項都掃描並處理完后,棧頂存放的就是最后的計算結果。
![]()
14.棧在遞歸中的應用?
遞歸是一種重要的程序設計方法。簡單地說,若在一個函數、過程或數據結構的定義中又應 用了它自身,則這個函數、過程或數據結構稱為是遞歸定義的,簡稱遞歸。 它通常把一個大型的復雜問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞歸 策略只需少量的代碼就可以描述出解題過程所需要的多次重復計算,大大減少了程序的代碼量。但在通常情況下,它的效率並不是太高。
將遞歸算法轉換為非遞歸算法,通常需要借助棧來實現這種轉換。
15.隊列在層次遍歷中的作用?
在信息處理中有一大類問題需要逐層或逐行處理。這類問題的解決方法往往是在處理當前層 或當前行時就對下一層或下一行做預處理,把處理順序安排好,待當前層或當前行處理完畢,就可以處理下一層或下一行。使用隊列是為了保存下一步的處理順序。下面用二叉樹層次遍歷的例子,說明隊列的應用。
![]()
16.隊列在計算機系統中的應用?
隊列在計算機系統中的應用非常廣泛,以下僅從兩個方面來簡述隊列在計算機系統中的作用:第一個方面是解決主機與外部設備之間速度不匹配的問題,第二個方面是解決由多用戶引起 的資源競爭問題。
對於第一個方面,僅以主機和打印機之間速度不匹配的問題為例做簡要說明。主機輸出數據給打印機打印,輸出數據的速度比打印數據的速度要快得多,由於速度不匹配,若直接把輸出的 數據送給打印機打印顯然是不行的。解決的方法是設置一個打印數據緩沖區,主機把要打印輸出的數據依次寫入這個緩沖區,寫滿后就暫停輸出,轉去做其他的事情。打印機就從緩沖區中按照先進先出的原則依次取出數據並打印,打印完后再向主機發出請求。主機接到請求后再向緩沖區寫入打印數據。這樣做既保證了打印數據的正確,又使主機提高了效率。由此可見,打印數據緩沖區中所存儲的數據就是一個隊列。
對於第二個方面, CPU (即中央處理器,它包括運算器和控制器)資源的競爭就是一個典型 的例子。在一個帶有多終端的計算機系統上,有多個用戶需要CPU 各自運行自己的程序,它們分別通過各自的終端向操作系統提出占用CPU 的請求。操作系統通常按照每個請求在時間上的先后順序,把它們排成一個隊列,每次把CPU 分配給隊首請求的用戶使用。當相應的程序運行結束或用完規定的時間間隔后,令其出隊,再把CPU 分配給新的隊首請求的用戶使用。這樣既能滿足每個用戶的請求,又使CPU 能夠正常運行。
17.矩陣的壓縮存儲
數據結構中,提供針對某些特殊矩陣的壓縮存儲結構。這里所說的特殊矩陣,主要分為以下兩類:
- 含有大量相同數據元素的矩陣,比如對稱矩陣;
- 含有大量 0 元素的矩陣,比如稀疏矩陣、上(下)三角矩陣;
針對以上兩類矩陣,數據結構的壓縮存儲思想是:矩陣中的相同數據元素(包括元素 0)只存儲一個。
第四章、串
快速喚起記憶知識框架:
18.串的模式匹配
子串的定位操作通常稱為串的模式匹配,他求的是子串(常稱模式串)在主串中的位置。
暴力模式匹配算法的思想是:從主串的第一個字符起,與子串的第一個字符比較,相等則繼續比較;不等則從主串的下一個位置起,繼續和子串開始比較,直到最后看是否匹配成功。
以下的子串為:‘abcac’:
![]()
改進的模式匹配算法-----KMP算法:
在暴力匹配中,每趟匹配失敗都是模式后移一位再從頭開始比較。而某趟已匹配相等的字符 序列是模式的某個前綴,這種頻繁的重復比較相當於模式串在不斷地進行自我比較,這就是其低效率的根源。因此,可以從分析模式本身的結構着手,如果已匹配相等的前綴序列中有某個后綴正好是模式的前綴,那么就可以將模式向后滑動到與這些相等字符對齊的位置,主串i指針無須回溯,並繼續從該位置開始進行比較。而模式向后滑動位數的計算僅與模式本身的結構有關,與主串無關。
(此處篇幅過長,感興趣可以直接百度KPM算法詳細了解,當然要求不高的可以直接跳過,知道大致思想即可,不要被問到一問三不知就可以)