鏈表課後複習題 - 王道

目錄

1.設計一個遞歸算法,刪除不帶頭結點的單鏈表L中所有值爲x的結點。

2.刪除帶頭結點的單鏈表L中所有值爲x的結點。

3.在帶頭結點的單鏈表L中從尾到頭反向輸出每個結點的值

4.帶頭結點單鏈表L中刪除一個最小值結點的比較高效的算法,假設最小值結點唯一

5.將帶頭結點的鏈表就地逆置

明日繼續更~


以下是幾道涉及到鏈表的代碼題。

注意涉及到鏈表的操作,一定要在紙上把過程先畫出來,再寫程序!

 

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;
    }
}

 

明日繼續更~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章