C语言线性链表基本操作

线性链表与顺序表的区别在于存储的结构不同,顺序表是物理位置相邻,逻辑也相邻,而链表物理位置不一定相邻但是逻辑相邻,这导致他查找,存取数据时需要一一遍历以找到所需要存取的位置,因为链表的相邻,相当于我不知道你具体在哪里,我只能看到前面和后面的人,若要找到某个人,就得一个一个问过去。基于链表的基本知识,我们可以创建这样一个链表。

  • 创建链表

先创建结点结构体,和上篇文章一样,我们仍然使用ElemType来作为我们数据类型的别名,前篇文章链接如下:

https://blog.csdn.net/xiaoyan4869/article/details/142053966

typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

以下是头插法创建单链表的代码

注意头插法输入数据需要倒序

void CreatList_L(LinkList &L,int n){
    //逆位数输入n个元素的值,建立带表头节点的单链线性表L
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;    //先建立一个带头节点的单链表
    for(int i=n;i>0;i--){
        LNode p=(LinkList)malloc(sizeof(LNode));    //生成新结点
        scanf("%?",&p->data);    //问号中的字符由输入值的类型决定
        p->next=L->next;    //新节点的下一个节点是头节点后的一个结点
        L->next=p;          //头结点链接新节点
    }
       

  • 查找结点

查找第i个结点,需要一个个顺序向后遍历,用j进行计数,记录遍历过的结点数量,然后用e来返回查到结点的元素值

Status GetElem_L(LinkList &L,int i,ElemType &e){
    LNode *p=L->next;    //从第一个存储数据的结点开始查找
    int j=1;
    while(p && j<i){
        p=p->next;    //遍历链表并计数找到第i个结点
        ++j;
    }
    if(!p || i>j)
        return ERROR;    //遍历到非法位置后返回error
    e=p->data;           //找到了i位置的数后赋值给e
    return OK;
}

  • 删除结点

如下图所示,删除结点只需要遍历到被删除结点的上一个位置,然后使上一个位置的结点链接到被删除结点的下一个位置就完成了。

Status ListDelete_L(LinkList &L,int i,ElemType &e){
    //在带头结点的单链表中删除第i个数并将删除的数返回e
    int j=0;
    LNode *p=L;
    while(!p && j<i-1){    //寻找第i-1个结点
        p=p->next;
    }
    LNode q=p->next;    //q等于p的下一个结点
    p->next=q->next;    //p的下一个结点等于q的下一个节点
    e=q->data;          //e的值为被删除的值   
    free(p);            //释放被删除的结点
}

  • 插入结点

如图是插入结点的示意图

插入结点的关键点在于先链接插入位置的后一个结点,以防止后续结点丢失,然后再链接前一个结点

Status LinkInsert_L(LinkList &L,int i,ElemType &e){
//在带头结点的单链线性表L中第i个位置前插入元素e
    LNode p=L,q;    
    int j=0;
    while(p && j<i-1){        //找到第i-1个结点
        p=p->next;
        j++;
    }
    if(!p || j>i-1) return ERROR;
    q=(LinkList)malloc(sizeof(LNode));    //创建新节点
    q->data=e;
    q->next=p->next;
    p->next=q;
    return OK;
    }

  • 合并链表

已知顺序表La和Lb的元素按值非递减排列,归并La和Lb得到新的顺序表Lc,Lc的元素也按值非递减排列

void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
    pa=La->next;    //pa,pb均指向两个链表的第一个元素
    pb=Lb->next;
    Lc=pc=La;
    while(pa && pb){        //逐个从La,Lb中一一取出元素,比较得出较小的元素值,放入新链表中
        if(pa->data <= pb->data){
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else{
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
        pc->next = pa?pa:pb;        //将La,Lb中剩余的元素放入链表c
   free(Lb);
}

链表比起顺序表,虽然查找,存取数据时间复杂度较高,必须逐个遍历才能找到指定的数据,但是优点也很突出,就是不需要连续的地址空间,也便于插入数据删除数据,只要改变指针指向就足够了,不需要一个一个后移数据,大大节省了时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值