目錄
1.設計一個遞歸算法,刪除不帶頭結點的單鏈表L中所有值爲x的結點。
4.帶頭結點單鏈表L中刪除一個最小值結點的比較高效的算法,假設最小值結點唯一
以下是幾道涉及到鏈表的代碼題。
注意涉及到鏈表的操作,一定要在紙上把過程先畫出來,再寫程序!
1.設計一個遞歸算法,刪除不帶頭結點的單鏈表L中所有值爲x的結點。
- 因爲不帶頭結點,所以表空這樣表示:L->next == NULL
- 需要新建一個結點來釋放內存,指向待刪除結點:LNode *p;
- 因爲是遞歸,搞清楚遞歸出口:L == NULL,從前往後刪除值爲val的結點:
代碼
- 只需要一個存儲待刪除結點的p就夠了
//刪除不帶頭結點的單鏈表L中所有值爲x的結點
void Del_x_3(LinkList &L, ElemType x){
LNode *p;
if(L == NULL) return;
if(L->next == x){
p = L;
L = L->next;
free(p);
Del_x_3(L, x);
}else{
Del_x_3(L->next, x);
}
}
這道題返回值爲空,不是因爲返回值地址相互連接在一起的,而是因爲在本來的鏈表中逐個刪除纔得到的新鏈表。原理就是逐個刪除等於x的結點。
2.刪除帶頭結點的單鏈表L中所有值爲x的結點。
這個不是遞歸算法,而是正常解法
- 設頭結點指針pre,第一個結點指針p,需要一個存儲待刪除結點的指針q
- 遍歷條件是p沒到頭:即p != NULL;
- 通過判斷p->data是否等於x來進行操作:如果等於刪除加上兩節點後移,不等於則直接兩節點後移
//刪除帶頭結點的單鏈表L中所有值爲x的結點。
void Del_x_2(LinkList &L, ElemType x){
LNode *p = L->next, *pre = L, *q;//新加兩個指針pre和p
while(p != NULL){
if(p->data == x){
q = p;
p = p->next;
pre->next = p;
free(p);
}else{
pre = p;
p = p->next;
}
}
}
這道題返回值爲空,也是通過遍歷逐個刪除值爲x的結點實現的,操作之後直接就得出了現在的鏈表
3.在帶頭結點的單鏈表L中從尾到頭反向輸出每個結點的值
- 如果有下一個結點的話,輸出下一個結點的值,然後再輸出自己
代碼
//在帶頭結點的單鏈表L中從尾到頭反向輸出每個結點的值
void R_print(LinkList L){
if(L->next != NULL){
R_print(L->next);
}
printf(L->data);
}
有頭結點比較方便,不必特殊考慮第一個結點
4.帶頭結點單鏈表L中刪除一個最小值結點的比較高效的算法,假設最小值結點唯一
從頭到尾遍歷單鏈表,用minp作爲指向最小值的指針,遍歷過程如果遇到更小值的就替換minp
- p指針工作指針,pre指針指向p的前驅;
- minp保存最小結點的指針,minpre保存最小值結點的前驅
一個一個遍歷就很高效了,因爲沒有重複遍歷,遍歷一次就夠了
//帶頭結點單鏈表L中刪除一個最小值結點的比較高效的算法,假設最小值結點唯一
LinkList DeleteMin(LinkList &L){
LNode *pre = L, *p = L->next;
LNode *minpre = pre, *minp = p;
while(p != NULL){
if(p->data < minp->data){
minp = p;
minpre = pre;
}
pre = p;
p = p->next;
}
minpre->next = minp->next;
free(minp);
return L;
}
minpre->next = minp->next; 和 free(minp); 這兩句就是刪除minp結點。
5.將帶頭結點的鏈表就地逆置
把頭結點摘下,然後從第一個結點開始,依次插入到頭結點後面直到最後一個結點
除了自帶的L指針外,還需要 p 和 r 指針,r 是 p 的後繼
//將帶頭結點的鏈表就地逆置
LinkList Reverse_L(LinkList L){
LNode *p, *r;
p = L->next;
L->next = NULL;//把頭結點摘出來
while(p != NULL){
r = p->next;
p->next = L->next;
L->next = p;
p = r;
}
}