C語言實現單鏈表面試題 ----基礎篇
這裡介紹單鏈表常見的面試題:
1. 比較順序表和連結串列的優缺點,說說它們分別在什麼場景下使用?
從結構分析:
(1)順序表是連續的儲存空間,支援隨機訪問,單鏈表不支援隨機訪問
(2)順序表插入、刪除效率較很低,時間複雜度為O(n)(除尾刪尾插),單鏈表插入、刪除效率較高,
時間複雜度為O(1)。
(3)順序表的快取記憶體效率更高,單鏈表快取記憶體效率低。
從空間開闢分析:
(1)順序表的空間開闢,往往存在這2^n的開闢原則。在開闢次數比較多時,會出現比較大的空間浪費。
(2)連結串列的空間 開闢是針對於單個節點的空間開闢,不存在多於的空間浪費,並且在碎片記憶體池的機制下,
可以有效的利用空間。
使用場景:
順序表往往用於查詢遍歷操作比較頻繁的情況下使用。連結串列則針對於資料刪除修改的多操作性上的情況下使用。
2.從尾到頭列印單鏈表
(1)暴力查詢(利用雙層迴圈)
(2)遞迴
3.刪除一個無頭單鏈表的非尾節點
條件:無頭單鏈表(只傳入刪除結點的位置pos)、非尾結點
方法:將pos的下一個結點的data域賦給pos的data域,刪除pos->next
程式碼:
4.在無頭單鏈表的一個節點前插入一個節點
利用3的思想,在此結點後插入一個結點,交換此節點與插入結點的data域
5.單鏈表實現約瑟夫環
約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。
6.逆置/反轉單鏈表
(1)定義三個變數 n0=NULL,n1=*ppnode,n2=(*ppnode)->next
程式碼:
(2)定義一個newhead 的結點
程式碼:
7.單鏈表排序
使用氣泡排序
8. 合併兩個有序連結串列,合併後依然有序
分情況:兩個均為空,一個為空一個不為空,兩個均不為空
Node* MergeList(Node* List1,Node* List2)
{
Node* list = NULL,*tail = NULL;
//其中一個連結串列為NULL的情況
if(List1 == NULL)
{
return List2;
}
if(List2 == NULL)
{
return List1;
}
//合併連結串列前的準備
if(List1->data < List2->data )
{
list = List1;
List1 = List1->next;
}
else
{
list = List2;
List2 = List2->next ;
}
tail = list;
//迴圈
while(List1&&List2)//注意迴圈結束的條件
{
if(List1->data < List2 ->data )
{
tail->next = List1;
tail = tail->next ;
List1 = List1->next ;
}
else
{
tail->next = List2;
tail = tail->next ;
List2 = List2->next;
}
}
if(List1 == NULL)
{
tail->next = List2;
}
else
{
tail->next = List1;
}
return list;
}
快慢指標問題
9.查詢單鏈表的中間節點,要求只能遍歷一次連結串列
分析:定義一個開指標fast和一個慢指標slow,快指標一次走兩步,慢指標走一步,當fast為Null時,slow即為中間結點(奇數個返回中間節點,偶數個返回中間的前一個結點)
10.查詢單鏈表的倒數第k個節點,要求只能遍歷一次連結串列
分析:(1)連結串列>k個結點(利用9的思想)
fast先走k步,然後slow、fast共同走
(2)連結串列不足k個結點
程式碼: