首先實現乙個無頭單鏈表
#include
#include
#include
typedef int datatype;
typedef struct listnode
listnode;
//列印
void printlist(listnode* plist)
printf("null");
printf("\n");
}//尾插
void pushback(listnode** pplist, datatype x)
//只有乙個節點
else
if ((*pplist)->next ==
null)
//多個節點
else
node->next = (listnode*)malloc(sizeof(listnode));
node->next->
data
= x;
node->next->next =
null;
}}//尾刪
void popback(listnode** pplist)
else
free(node);
node =
null;
}}//頭插
void pushfront(listnode** pplist, datatype x)
else
}//頭刪
void popfront(listnode** pplist)
else
}//查詢
listnode* find(listnode* plist, datatype x)
plist = plist->next;
}return
null;
}//在pos的前面插入乙個節點
void insert(listnode** pplist, listnode* pos, datatype x)
else
tmp =(listnode*) malloc(sizeof(listnode));
tmp->
data
= x;
head->next = tmp;
tmp->next = pos;
}}//刪除乙個節點
void erase(listnode** pplist, listnode* pos)
else
tmp->next = pos->next;
free(pos);
pos =
null;
}}
1.比較順序表和煉表的優缺點,說說它們分別在什麼場景下使用?
空間上的比較(space)
空間的開闢:
順序表的實現一般是實現連續開闢一段空間(或根據需求動態連續開闢空間),然後在進行資料的增刪查改(靜態順序表),所以順序表一般是固定空間大小的;
單鏈表則是一次只開闢乙個結點的空間,用來儲存當前要儲存的資料及指向下乙個結點或null的指標,所以單鏈表的空間大小是動態變化的。
空間的使用:
當我們不知道要儲存多少資料時,用順序表來開闢的空間如果太大,就會造成一定程度上的浪費。
用單鏈表實現時,因為是每需要儲存乙個資料時,才開闢乙個空間,雖然有非資料項的指標佔空間,但相比順序表來說,浪費不是那麼明顯。(因為鍊錶每次都是開闢的位置都是隨機的,那麼可能會把這塊空間搞得七零八碎,出現很多小的一般使用不到的碎片空間)
對cpu快取記憶體的影響:
順序表的空間一般是連續開闢的,而且一次會開闢儲存多個元素的空間,所以在使用順序表時,可以一次把多個資料寫入快取記憶體,再寫入主存,順序表的cpu快取記憶體效率更高,且cpu流水線也不會總是被打斷;
單鏈表是每需要儲存乙個資料才開闢一次空間,所以每個資料儲存時都要單獨的寫入快取記憶體區,再寫入主存,這樣就造成了,單鏈表cpu快取記憶體效率低,且cpu流水線會經常被打斷。
時間上的比較(time)
查詢隨機元素的時間複雜度:
順序表訪問隨機元素的時間複雜度是o(1),而單鏈表訪問隨機元素的時間複雜度是o(n)。
隨機位置插入、刪除元素的時間複雜度:
順序表在插入隨機位置插入、刪除元素的平均時間複雜度是o(n),
單鏈表在插入隨機位置插入、刪除元素的時間複雜度是o(1)。
應用場景:
根據時間複雜度比較:
在查詢操作使用的比較頻繁時,使用順序表會好一些;
在插入、刪除操作使用的比較頻繁時,使用單鏈表會好一些。
2.從尾到頭列印單鏈表
void printheadtotail(listnode* plist)
while (plist)
printf("null\n");
}//遞迴方式
void printheadtotail(listnode* plist)
printf("%d->", plist->
data);
printheadtotail(plist->next);
}
3.刪除乙個無頭單鏈表的非尾節點
無頭單鏈表無法找到pos的前乙個節點,只能把pos後乙個節點的內容賦值給pos然後刪掉pos後乙個節點
void erasenotail(listnode* pos)
else
}
4.在無頭單鏈表的乙個節點前插入乙個節點
先申請乙個節點插入到pos後面,然後再與pos的內容相交換
void
frontinsert(listnode* pos,datatype x)
5.單鏈表實現約瑟夫環
listnode* josephring(listnode *plist, datatype k)
plist->
data
= plist->next->
data;
tmp = plist->next;
plist->next = plist->next->next;
free(tmp);
tmp =
null;
}return plist;
}
6.逆置/反轉單鏈表
listnode* reverse(listnode* plist)//逆置反轉單鏈表
return newhead;
}
7.單鏈表排序(氣泡排序&快速排序)
listnode *bubblesort(listnode *plist)//單鏈表排序(氣泡排序&快速排序)
else
cur = next;
next = next->next;
}tail = cur;
}cur = next = tail =
null;
}return plist;
}
8.合併兩個有序鍊錶,合併後依然有序
listnode *merge(listnode *plist1,listnode *plist2)
if (plist2 ==
null)
while (plist1 && plist2)
else
if (plist ==
null)
else
}if (plist1 ==
null)
else
return plist;
}
9.查詢單鏈表的中間節點,要求只能遍歷一次鍊錶
listnode *findmidnode(listnode *plist)
return slow;
}
10.查詢單鏈表的倒數第k個節點,要求只能遍歷一次鍊錶
listnode *findtailknode(listnode *plist,int k)
while (fast->next != null)
return slow;
}
C語言實現單鏈表面試題 高階
判斷單鏈表是否帶環?若帶環,求環的入口點 listnode judge band listnode plist 判斷單鏈表是否帶環?若帶環,求環的入口點?if fast next null fast next next null return null fast plist while fast s...
C語言實現單鏈表面試題(基礎篇)
順序表 1.記憶體中位址連續 2.長度不可變更 3.支援隨機查詢 可以在o 1 內查詢元素 4.適用於需要大量訪問元素的 而少量增添 刪除元素的程式 鍊錶 1.記憶體中位址非連續 2.長度可以實時變化 3.不支援隨機查詢 查詢元素時間複雜度o n 4.適用於需要進行大量增添 刪除元素操作而對訪問元素...
C語言實現單鏈表面試題(基礎篇)
順序表 1.記憶體中位址連續 2.長度不可變更 3.支援隨機查詢 可以在o 1 內查詢元素 4.適用於需要大量訪問元素的 而少量增添 刪除元素的程式 鍊錶 1.記憶體中位址非連續 2.長度可以實時變化 3.不支援隨機查詢 查詢元素時間複雜度o n 4.適用於需要進行大量增添 刪除元素操作而對訪問元素...