一、引言
上篇文章我们知道了顺序表的缺点:
- 插入和删除操作需要移动大量元素。
- 数组的大小不好确定。
- 存储分配需要一整段连续的存储空间,不够灵活,造成很多碎片(空闲的空间得不到利用)。
所以我们就引入了单链表
二、简述单链表
单链表中逻辑上相邻的两个元素在物理位置上不相邻,一个结点分为数据域和指针域,如下图,1的指针域(指针变量)存放2的起始地址,以此类推,就很像我们生活中的火车,最后一个结点的指针域为NULL,当我们在遍历的时候遇到NULL,就明白是单链表的结束
括号外面的LNode是别名等价于struct LNode,LinkList等价于struct LNode *LinkList
三、单链表的实现
头指针:链表中第一个结点的存储位置,用来标识单链表
头结点:在单链表的第一个结点(a1)之前附加的一个结点,为了操作的方便(带头结点就是头结点没数据)
若链表有头结点,则头指针永远指向头结点,不论链表是否为空,头指针均不为空,头指针是链表的必要元素,标识一个链表。
头结点为了操作的方便,其数据域一般为空,或者存放链表的长度。有头结点后,对在第一结点前插入和删除第一结点的操作就统一了 ,不用频繁重置头指针。但头结点不是一定要的。
头插、尾插、中间插如下图
(a)(b)插入的代码:
这里的p即为代码中的L(链头)
(c)插入的代码:
四、代码
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
typedef int ElemType;//单链表中的元素类型
//单链表结点的定义
typedef struct LNode{//单链表结点类型
ElemType data;//数据域
struct LNode *next;//指针域 指向下一个结点
}LNode,*LinkList;//*LinkList等价于struct LNode *LinkList
/*头插法建立单链表*/
LinkList createListH(LinkList &L)
{
LNode *q;
int n;
L=(LinkList)malloc(sizeof(LNode));//带头结点的链表
L->next=NULL;//L.data没存数据
scanf("%d",&n);//读取数据
while (n!=999)
{
q=(LNode*)malloc(sizeof(LNode));//申请新空间给q
q->data=n;//把读取的值给q->data
q->next=L->next;//新结点的next指针指向链表的第一个元素(第一个放数据的元素)
L->next=q;
scanf("%d",&n);//继续读取
}
return L;
}
/*尾插法建立单链表*/
LinkList createListT(LinkList &L)
{
L=(LinkList)malloc(sizeof(LNode));//带头结点的链表
LNode *q,*r=L;//写成LinkList q,r=L;也可以,这里r一开始就是表尾结点指向链表尾部
int n;
scanf("%d",&n);//读取数据
while (n!=999)
{
q=(LNode*)malloc(sizeof(LNode));//申请新空间给q
q->data=n;//把读取的值给q->data
r->next=q;//尾部结点指向新结点
r=q;//r指向新的表尾结点
scanf("%d",&n);//继续读取
}
r->next=NULL;//尾指针的next指针赋值为空
return L;
}
void printList(LinkList L)//这里L没用引用,不会改变主函数里面的L
{
L=L->next;
while (L!=NULL)
{
printf("%3d",L->data);
L=L->next;//打印完数据指向下一个结点继续打印,直到L=NULL
}
printf("\n");
}
int main()
{
LinkList L;//链头 结构体指针类型
LinkList pfind;//存储拿到的某个结点
createListH(L);//输入 1 2 3 4 5
//createListT(L);
printf("头插法打印链表元素如下:\n");
printList(L);//打印链表
return 0;
}
1、scanf("%d",&n);输入时会忽略空格 ,可以一次性输一排,空格隔开
2、 注意尾插法中一定要把尾指针的next指针赋值为空(r->next=NULL;),不然会出现异常,不是NULL,就会指向申请的空间的地址,在打印链表时进入while循环判断时不等于NULL,就会去拿它指向的空间的数据(L->data),而这个地址是不可读的,这时候去访问就出现异常
五、结果
输入1 2 3 4 5 999(遇到999回车结束输入)
遇到的bug:尾插法输入完直接结束,如图
调试如下:
发现问题:
解决问题:链头要先申请空间再赋值给结点r
原创不易,转载请注明出处: