数据结构之单链表与循环链表
一、链表的结构表示
(一)相关术语:
1.节点:数据元素的存储映像。由数据域和指针域两部分组成。
2.链表:n个节点由指针域组成一个链表。它是线性表的链式存储映像,称为线性表的链式存储结构
单链表的结构:
typedef struct Lnode{ //声明结点的类型和指向节点的指针类型
ElemType data //结点的数据域
struct Lnode *next //结点的指针域
}Lnode, *LinkList //LinkList 为指向结构体Lnode的指针类型
(二)单链表的相关操作:
1.链表的初始化
Status InitList_L(LinkList &L){ //
L = new LNode // 生成新的结点作头结点,用头指针L指向头结点
L->next = NULL // 将头节点的指针域置空
return OK //
}
2.判断链表是否为空
int ListEmpty(LinkList L) { //如果为空表,返回1否则返回0
if(L->next) { //非空
return 0
} else {
return 1 //
}
}
3.销毁单链表L
Status DestroyList_L(LinkList &L) { //销毁单链表
Lnode *p // 定义一个变量用于储存单链表的后续 ,其中L、P都是指针,存储的地址,
while (L) { // 循环遍历直到为空
P = L // 将L存储的地址赋值给P
L = L->next // L取到下一个链表的地址
delete P // 销毁P地址指向的内容
}
}
4.清空单链表(清空内容,但是链表仍然存在)
Status DestroyList_L(LinkList &L) { // 清空单链表
Lnode *p ,*q // 因为要保留头节点,需要定义两个指针变量,一个存储需要销毁的结点,一个存储销毁的下一个结点
p = L->next // 从L.next开始清除,保留头节点
while (P) { // 没到尾节点
q=p->next // 保留下一结点链表的位置
delete P // 消除p的位置
p = q // 重新赋值
}
L->next = NULL // 便利完除头节点,其余结点已经全部消除,将头结点的指针域赋值为空
return OK
}
5.求链表L的表长
int ListLength_L(LinkList L) {
LinkList p
p = L->next
i=0
while(p) {
i++
p =p->next
}
return i
}
6.单链表的取值
Status GetElem_L (LinkList L,int i,ElemType &e) { //获取线性表L中的某个数据元素的内容,通过变量e返回
p = L->next ; j=1 // 初始化
while(p && j<1) { //向后变量除非达到第i个的位置,并且p存在
p=p->next; ++j
}
if(!p || j>i) return ERROR //判断第i个元素是否存在
e=p->data //取第i个元素
return OK
}// GetElem_L
7.单链表的查找
Lnode *LocateElem_L (LinkList L,Elemtype e) {
//在线性表L中查找值为e的数据元素
//找到返回L中值为e的数据元素的地址,否则返回null
p = L->next;
while(p && p->data != e){
p = p->next
}
return P
}
8.单链表的插入操作
Status ListInsert_L (LinkList &L.int i, ElemType e) { //在l中第i个元素之前插入数据元素e
p = L;j = 0;
while (p && j<i-1) { // 寻找第i-1个结点,p指向i-1结点
p=p->next;
++j
}
s = new Lnode; //生成新结点s,将结点s的数据置为e
s->data = e
s->next = p->next //将结点i-1的next赋值给插入结点
p->next = s //将插入结点赋值给i-1的next
return OK
}
9. 单链表的删除操作
Status ListDelete_L (LinkList &L.int i, ElemType &e) { //在L中删除第i个元素
p = L;j = 0;q=0;
while (p->next && j<i-1) { // 寻找第i-1个结点,p指向i-1结点
p=p->next;
++j
}
if(!(p->next)||j>i-1) return ERROR //判断删除位置是否合理
q=p->next //找到第i个结点的位置
p->next = q->next //将第i+1个结点的位置赋值给i-1的next
e = q->data //保存删除结点的数据域
delete q //释放结点的空间
return OK
}
10.单链表的的建立
1.头插法(从最后一个结点开始,依次将各结点插入到链表的前端)
void CreateList_H(LinkList &L, int n) {
L = new LNode
L->next = NULL // 创建一个头结点
for (i = n, i>0, --i) {
p = new LNode // 生成新结点 p
cin>>p->data // 输入元素值
p->next = L->next // 将头结点的next赋值给新结点
L->next = p // 将新结点赋值给头结点的next
}
}
2.尾插法(元素插入在链表尾部)
void CreateList_R(LinkList &L, int n) {
L = new LNode
L->next = NULL // 创建一个头结点
r = L // 尾指针r指向头结点
for (i = 0, i<n, ++i) {
p = new LNode // 生成新结点 p
cin>>p->data // 输入元素值
p->next = NULL // 将头结点的next赋值给新结点
r->next = p // 将新结点赋值给头结点的next
}
}
(三)循环链表
1.循环链表的概论
由于循环列表中尾指针的next指向了头指针,所以没有NULL指针,在涉及遍历的时候,其终止条件就不再非循环链表那样判断p或p->next是否为空,而是判断它们是否等于头指针
2.链表的合并
//合并尾指针的两个循环链表
LinkList Connect(LinkList Ta, linkList Tb) {
p = Ta->next //p存表头结点
Ta->next = Tb ->next->next //Tb 表头链接Ta 表头
delete Tb->next // 释放Tb表头结点
Tb->next = p //修改指针
return Tb
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix