单链表的建立

前言

在上一篇文章——中我们学习了单链表的插入和删除,今天这篇文章就来讲述一下单链表的建立。今天探讨的也是基于带头结点的单链表。

建立链表

如果要建立一个链表我们需要先初始化

bool InitList(LinkList &L){
    L = (LNode *)malloc(sizeof(LNode));	// 分配一个头结点
    if(L==NULL)			// 内存不足,分配失败
        return false;
    L->next = NULL;		// 让头结点的指针指向NULL(链表为空表)
    
    return true;
}

由于在单链表的定义中已经比较详细的讲述了链表的初始化,故在此不再赘述初始化代码。

尾插法

尾插法顾名思义就是在尾部(后面)插入结点。在前几篇文章中我们讲述过如何按位序插入,在这里我们可以引用该代码如下:

bool ListInsert(LinkList &L,int i,ElemType e){
    if(i<i)
        return false;
    LNode *p;			// 指针p指向当前扫描到的结点
    int j = 0;			// 当前p指针指向的是第几个结点
    p = L;				// L指向头结点,头结点时第0个结点(不存放数据)
	while(p!=NULL && j<i-1){
        p = p->next;
        j++;
    }
    if(p=NULL)			// i值不合法
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;		// 将结点s连接到p之后
    
    return true;		// 插入成功
}

如果当我们一次性有多个数据想要插入时,就可以使用循环的逻辑去实现

while 循环{
    每次取一个数据元素e;
    ListInsert(L,length+1,e);	// 插入到尾部
    length++
}

每次循环我们取一个要插入的元素e,并且调用按位序查找的函数,最后再让链表长度+1。

虽然这样可以实现我们的插入操作,但是我们会发现每一次调用按位序插入,都要从表头开始遍历到,最后一个元素后才能开始插入,这样的话我们如果要插入n个元素,那么循环的次数就要:0+1+2…+n-1,这样就会导致时间复杂度为O(n)。但是其实根本不需要每次都从头开始。于是我们想到可以设置一个指针指向链表中的最后一位元素,直接在该指针指向的最后一个结点后面插入元素,并且再插入完之后,将指针再次指向新插入的结点(最后的结点),以此后插操作:

LinkList List_TailInsert(LinkList &L){
    int x;
    L = (LinkList)malloc(sizeof(LNode));		// 创建头结点
    LNode *s,*r = L;							// 创建两个指针指向头结点
    scanf("%d",&x);								// 输入结点值
    while(x!=9999){								// 输入9999表示结束
        s = (LNode *)malloc(sizeof(LNode));		// 创建新的结点
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d",&x);
    }
    r->next = NULL;								// 尾结点指针置空
    
    return L;
}

这里简单的介绍一下代码:

  1. 创建一个头结点
  2. 创建两个指针,都指向头结点
  3. 让用户输入要插入的值
  4. 循环终止条件为用户输入的值9999
    • 这里不一定要9999,只是我们设置的一个退出的值,你可以任意设置8888等
  5. 循环内就是上述说到的插入操作
    • s指针指向新创建的结点,r指针指向链表中最后一个结点,在新结点进行完插入数据的操作后,要将原先链表的最后一个结点指向新结点,这样才算完成了新结点在链表中的插入操作,也就是在原先链表中最后一个结点的后面插入新结点,最后r在指向s指向的结点(r永远要指向链表的最后一个结点)
  6. 用户继续输入值,直至输入9999,退出循环
  7. r指针置空,其实就是链表中的最后一个结点指针置空

举例

这里我们分别输入10、16、27、9999来看看是程序如何操作的。

创建头结点,并且将r、s指针指向头结点

image-20220709222634753

输入10,会先创建一个结点将s指向新结点,并且将10元素值插入

image-20220709222720519

将r指向的结点的指针指向s指向的新结点

image-20220709222758929

将r指向s指向的结点(新结点)

image-20220709222851353

中间16、27的操作类似,我们着重来看输入9999的操作

image-20220709222943667

退出循环,并且让r指向的结点指向NULL

头插法

头插法,顾名思义就是每次插入元素的时候都在链表的头部插入数据。

插入新的结点

image-20220709223231568

插入新的结点

image-20220709223250872

头插法的思路其实也非常简单,头插法是在头结点的后面插入元素,其实就是对头结点进行后插操作。所以每次插入新结点的时候,都对头结点进行后插操作即可。

LinkList List_HeadInsert(LinkList &L){
    LNode *s;
    int x;
    L = (LinkList)malloc(sizeof(LNode))		// 创建头结点
    L->next = NULL;							// 将头结点指针置空,为空表
    scanf("%d",&x);							// 输入结点的值
    while(x!=9999){
        s = (LNode *)malloc(sizeof(LNode));	// 创建新结点
        s->data = x;
        s->next = L->next;
        L->next = s;						// 将新结点插入表中,L为头指针
        scanf("%d",&x);
    }
    retrun L;
}

应用:逆置

单链表的头插法可以实现单链表的逆置。比如我们插入10、16、27,那么使用头插法的话,在单链表中的元素排列就为:27、16、10

结束语

已同步更新至个人博客:https://www.hibugs.net/index.php/sqlistcrt/

本人菜鸟一枚,仅分享学习笔记和经验。若有错误欢迎指出!共同学习、共同进步 😃

如果您觉得我的文章对您有所帮助,希望可以点个赞和关注,支持一下!十分感谢~(若您不想也没关系,只要文章能够对您有所帮助就是我最大的动力!)

下一篇文章传送门:正在更新,敬请期待…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值