*单链表之头插法、尾插法、按值按序号查找、插入节点、删除节点操作
承接上一篇继续学习:顺序表应用
单链表定义:
线性表的链式存储又称单链表,它是指通过任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继指针。单链表节点如下图所示。
data | next |
---|
next:存放后继指针。data:数据域,存放数据
优缺点:单链表解决顺序表需要大量连续存储单元的缺点,但单链表附加了指针域,存在浪费存储空间的缺点。
单链表是非随机存取的存储结构,不能直接找到表中的某个特定节点,所以查找时需要从表头开始遍历,依次查找。
头结点:在单链表第一个结点之前附加一个结点为头结点。(头结点的指针域指向第一个元素的结点)
头结点与头指针区分:不管带不带头结点,头指针始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,结点内通常不存储信息
引入头结点的优点:
1.由于第一个数据结点的位置被存放在头结点的指针域中,福哦一在链表的第一个位置上的操作和在表的其他位置上的操作一致,无需进行特殊处理
2.无论链表是否为空,其头指针都指向头结点的非空指针(空表中头结点的指针域为空),因此空表和非空表的处理也得到了统一。
基本操作
头插法建立链表
从一个空表开始,生成新结点,并将读到的数据存放到节点的数据域中,然后将新结点插入到当前链表的表头
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;
scanf("%d", &x);
}
return L;
2.采用尾插法建立链表
LinkList List_TailInsert(LinkList &L)
{
int x;
L=(LinkList)malloc(sizeof(LNode));
LNode *s, * r = L;//r是表尾指针
scanf("%d", &x);
while(x!= 9999){
s= (LNode*)malloc(sizeof(LNode));
s->data =x;
r->next = s;
r= s;//r指向新的表为节点
scanf("%d", &x);
}
r->next = NULL;
return L;
}
3.按序号查找结点值
在单链表中从第一个结点出发,顺时针next域逐个往下搜索,直到找到第i个结点为止,否则返回最后一个结点指针域NULL。
LNode *GetElem(LinkList L , int i)
{
int j = i;
LNode *p = L->next;
if(i == 0)
return L;
if(i < 1)
return NULL;
while(p&&j < i){
p = p ->next;
j++;
}
return p;
}
4.按值查找表结点
从单链表的第一个结点开始,由前往后一次比较表中各结点数据域的值,若某结点数据域的值等于给定值e,则返回该结点的指针;若整个单链表中没有这样的结点,则返回NULL。
LNode *(LocateElem(LinkList L, ElemType e))
{
LNode *p = L->next;
while(p != NULL && p->data!=e)
p=p->next;
return p;
}
5.插入结点操作
插入节点操作将值为x的新结点插入到单链表的第i个位置上。先检查插入位置的合法性,然后找到待插入位置的前驱结点,即第i-1个结点,再在气候插入新结点。
p = GetElem(L, i -1);
s -> next = p -> next;
p - > next = s;
6.删除结点操作
删除结点操作是将单链表的第i个节点删除。先检查删除位置的合法性,后查找表中第i-1个结点,即被删结点的前驱结点,再将其删除。
操作过程
p = GetElem(L, i -1 );//查找删除位置的前驱结点
q= p -> next;//令q指向被删除结点
p -> next = q->next;//将*q结点从链表中“断开”
free(q);//释放后继结点的存储空
工程代码:后续发布