C语言-中级阶段-12单链表的删除&考研真题实战

文章讲述了单链表的删除操作,包括检查索引合法性并调整节点,以及考研真题中的链表中间结点删除、尾部插入、逆置和合并操作的实现,涉及时间复杂度分析。
摘要由CSDN通过智能技术生成

1.单链表的删除操作实战

思路:判断i值是否合法 >> 找到第i-1个元素 >> 删除第i个元素并释放对应结点空间 >> 结束

代码:

LinkList list_pos_search(LinkList L,ElemType search_pos)
{
    if(search_pos<0)
    {
        return NULL;
    }
    int j;
    for(j=0;j<search_pos;j++)
    {
        L=L->next;
    }
    return L;
}

bool list_delete(LinkList L,ElemType delete_figure)
{
    LinkList m;
    m=list_pos_search(L,delete_figure-1);
    if(NULL==m)
    {
        return false;
    }
    LinkList n;
    n=m->next;
    m->next=n->next;
    free(n);
    return true;
}

注意:删除链表过程中头结点没有赋值、没有申请空间,就叫没有改变头结点,子函数就不需要加“&”符号
举例:删除第一个结点时,头指针的指针域会被赋予NULL(这种不算改变头指针)。而利用头插和尾插创建链表当然改变了头指针,这是从无到有的过程

2.考研真题实战

题目:

思路分析:

找到中间结点 >> 对后半部分进行逆置 >> 重新合并两个链表

1>设计思想

2>代码实战

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;

typedef struct node{
    ElemType data;
    struct node *next;
}NODE,*LinkList;

void list_tail_insert(LinkList &L)
{
    L=(LinkList)malloc(sizeof(NODE));
    ElemType x;
    scanf("%d",&x);
    LinkList s,r=L;
    while(x!=9999)
    {
        s=(LinkList)malloc(sizeof(NODE));
        s->data=x;
        r->next=s;
        r=s;
        scanf("%d",&x);
    }
    r->next=NULL;
}

void print_list(LinkList L)
{
    L=L->next;
    while(L)
    {
        printf("%3d",L->data);
        L=L->next;
    }
    printf("\n");
}

void divide_list(LinkList L,LinkList &L2)
{
    L2=(LinkList)malloc(sizeof(NODE));
    LinkList p,q;
    p=q=L->next;     //这两行代码可优化为1行
//    q=L->next;
    while(p)
    {
        p=p->next;
        if(NULL==p)
        {
            break;                  //return;       //这里不应该是return,而是break
        }
        p=p->next;
        if(NULL==p)
        {
            break;                  //return;       //这里不应该是return,而是break
        }
        q=q->next;
    }
    L2->next=q->next;
    q->next=NULL;
}

void reverse(LinkList L2)
{
    LinkList r,s,t;
    r=L2->next;  //下方应该增加r为空的判定条件,即L2链表内无元素的情况就不需要逆转了
    if(NULL==r)
    {
        return;
    }
    s=r->next;
    if(NULL==s)
    {
        return;
    }
    t=s->next;
//    while(s)             //循环条件设定为t
//    {
//        s->next=r;
//        if(NULL==t)       //以下三行(含本行)不应这样设置
//        {
//            break;
//        }
//        t=t->next;        //假若t的下一个结点是NULL,则会造成宕机,导致r、s和t全部为NULL
//        s=t;
//        r=s;
//    }
//                          //循环结束还需要s->next=r反向链接一次,否则接不上
    while(t)
    {
        s->next=r;
        r=s;
        s=t;
        t=t->next;
    }
    s->next=r;
    L2->next->next=NULL;
    L2->next=s;
}

void merge(LinkList L,LinkList L2)  //合并L2不需要加引用,这是错误的,加不加引用永远只看改变头指针没有
{
    LinkList pcur,p,q;
    pcur=L->next;
    q=L2->next;
    p=pcur->next;
    while(p!=NULL&&q!=NULL)
    {
        pcur->next=q;
        pcur=pcur->next;
        q=q->next;
        pcur->next=p;
        p=p->next;
        pcur=pcur->next;
    }                              //循环结束后还存在L或L2链表中谁多一个元素的问题,所以需要加上if来将各自多的结果链接上pcur
    if(p!=NULL)
    {
        pcur->next=p;
    }
    if(q!=NULL)
    {
        pcur->next=q;
    }
}
int main() {
    LinkList L;
    list_tail_insert(L);
    print_list(L);
    printf("********************\n");
    LinkList L2;
    divide_list(L,L2);
    print_list(L);
    print_list(L2);
    printf("********************\n");
    reverse(L2);
    print_list(L2);
    printf("********************\n");
    merge(L,L2);
    free(L2);                  //合并后要free掉L2链表的内存占用
    print_list(L);
    return 0;
}

3>时间复杂度分析

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值