前言
在上一篇文章——中我们学习了单链表的插入和删除,今天这篇文章就来讲述一下单链表的建立。今天探讨的也是基于带头结点的单链表。
建立链表
如果要建立一个链表我们需要先初始化
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;
}
这里简单的介绍一下代码:
- 创建一个头结点
- 创建两个指针,都指向头结点
- 让用户输入要插入的值
- 循环终止条件为用户输入的值9999
- 这里不一定要9999,只是我们设置的一个退出的值,你可以任意设置8888等
- 循环内就是上述说到的插入操作
- s指针指向新创建的结点,r指针指向链表中最后一个结点,在新结点进行完插入数据的操作后,要将原先链表的最后一个结点指向新结点,这样才算完成了新结点在链表中的插入操作,也就是在原先链表中最后一个结点的后面插入新结点,最后r在指向s指向的结点(r永远要指向链表的最后一个结点)
- 用户继续输入值,直至输入9999,退出循环
- r指针置空,其实就是链表中的最后一个结点指针置空
举例
这里我们分别输入10、16、27、9999来看看是程序如何操作的。
创建头结点,并且将r、s指针指向头结点
输入10,会先创建一个结点将s指向新结点,并且将10元素值插入
将r指向的结点的指针指向s指向的新结点
将r指向s指向的结点(新结点)
中间16、27的操作类似,我们着重来看输入9999的操作
退出循环,并且让r指向的结点指向NULL
头插法
头插法,顾名思义就是每次插入元素的时候都在链表的头部插入数据。
插入新的结点
插入新的结点
头插法的思路其实也非常简单,头插法是在头结点的后面插入元素,其实就是对头结点进行后插操作。所以每次插入新结点的时候,都对头结点进行后插操作即可。
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/
本人菜鸟一枚,仅分享学习笔记和经验。若有错误欢迎指出!共同学习、共同进步 😃
如果您觉得我的文章对您有所帮助,希望可以点个赞和关注,支持一下!十分感谢~(若您不想也没关系,只要文章能够对您有所帮助就是我最大的动力!)
下一篇文章传送门:正在更新,敬请期待…