链表课后复习题 - 王道

目录

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

 

明日继续更~

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