数据结构---线性表的链式表示和实现
线性表的链式表示和实现
存储结构特点:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)
逻辑次序和物理次序不一定相同,对于数据元素来说,存储本身的信息还有后继的信息
访问时只能通过头指针进入链表,并通过每个结点的指针域向后顺序扫描其余结点
数据域:存储数据元素信息
指针域:存储直接后继存储位置的域,通常称作指针或链
单链表:
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;// LinkList 为指向结构体 LNode 的指针类型
首元结点:存储第一个元素的结点
头结点:首元结点之前附设的结点,指针域指向首元结点
头指针:指向链表第一个结点的指针
顺序表---随机存储 链表---顺序存储
单链表基本操作实现
1.初始化---构造一个空表
(1)生成新结点作为头结点,用头指针L 指向头结点。
(2)头结点的指针域置空。
Status InitList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
2.取值
(1)用指针p指向首元结点,用j做计数器初值赋为1。
(2)从首元结点开始依次顺着链域next 向下访问,只要指向当前结点的指针 p 不为空(NULL), 并且没有到达序号为i的结点,则循环执行以下操作:
- p指向下一个结点;
- 计数器j相应加1;
(3)退出循环时, 如果指针p为空, 或者计数器j大于i, 说明指定的序号i值不合法(i大于表长n或i小于等于0), 取值失败返回ERROR; 否则取值成功, 此时j=i时,p所指的结点就是要找的第i个结点,用参数e保存当前结点的数据域, 返回OK。
Status GetElem(LinkList L,int i,ElemType &e)
{
p=L->next;
j=i;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i)
return ERROR;
e=p->data;
return OK;
}
3.查找
(1)用指针p指向首元结点 。
(2)从首元结点开始依次顺着链域next向下查找, 只要指向当前结点的指针p不为空, 并且p所指结点的数据域不等于给定值e, 则循环执行以下操作: p指向下一个结点 。
(3)返回p。若查找成功,p此时即为结点的地址值,若查找失败,p的值即为NULL。
LNode *LocateELem(LinkList L,Elemtype e)
{
p=L->next;
while(p&&p->date!=e)
{
p=p->next;
}
return p;
}
4.插入
(1)查找结点ai-1并由指针p指向该结点。
(2)生成一个新结点*s
(3)将新结点 的数据域置为 e。
(4)将新结点*s 的指针域指向结点ai
(5)将结点*p 的指针域指向新结点 *s。
Status Listinsert(LinkList &L,int i,ElemType e)
{
p=L;j=O;
while (p && (j<i-1))
{p=p->next;++j;}
if (!p I j>i- I 1) return ERROR;
s=new LNode;
s->data= e;
s->next=p->next;
p->next=s;
return OK;
}
5.删除
(1)查找结点ai-1 并由指针p指向该结点。
(2)临时保存待删除结点ai的地址在q中 ,以备释放。
(3)将结点*p的指针域指向ai的直接后继结点。
(4)释放结点ai的空间。
Status ListDelete(LinkList &L,int i)
{
while ((p->next) && (j<i-1))
{p=p->next; ++j;}
if (! (p->next) 11 (j>i-1)) return ERROR;
q=p->next;
p->next=q->next;
delete q;
return OK;
}
6.创建单链表---每个链表占用的空间不需预先分配划定,而是由系统按需即时生成。
从空表的初始状态起,依次建立各元素结点,并逐个插入链表。
1.前插法
前插法是通过将新结点逐个插入链表的头部(头结点之后)来创建链表,每次申请一个新结点,读入相应的数据元素值,然后将新结点插入到头结点之后。
(1)创建一个只有头结点的空链表。
(2)根据待创建链表包括的元素个数n, 循环n次执行以下操作:
• 生成一个新结点p;
• 输入元素值赋给新结点 * p的数据域;
• 将新结点p插入到头结点之后。
void CreateList_H(LinkList &L,int n)
{
L=new LNode;
L->next=NULL;
for(i=O;i<n;++i)
{
p=new LNode;
cin>>p->data;
p->next=L->next;L->next=p;
}
}
2.后插法
后插法是通过将新结点逐个插入到链表的尾部来创建链表。 同前插法一样, 每次申请一个新结点, 读入相应的数据元素值。 不同的是, 为了使新结点能够插入到表尾, 需要增加一个尾指针r指向链表的尾结点。
(1)创建一个只有头结点的空链表。
(2)尾指针r初始化, 指向头结点。
(3)根据创建链表包括的元素个数n, 循环n次执行以下操作:
• 生成一个新结点* p;
• 输入元素值赋给新结点 * p 的数据域;
• 将新结点* p 插入到尾结点* r之后;
• 尾指针* r指向新的尾结点* p。
void CreateList_R(LinkList &L,int n)
{
L=new LNode;
L->next=NULL;
r=L;
for(i=O;i<n;++i)
{
p=new LNode;
cin>>p->data;
p->next=NULL; r->next=p;
r=p;
}
}
代码实现
#include<iostream>
using namespace std;
typedef struct LNode
{
int data;
struct LNode* next;
}LNode, * LinkList;
bool InitList(LinkList& L);
void ShowList(LinkList L);
void CreateList(LinkList& L, int n);
void FoundList(LinkList L, int e);
void InsertList(LinkList& L, int i, int e);
void DeleteList(LinkList& L, int i);
int main()
{
int n, e, a, b, c;
LinkList L;
InitList(L);
cout << "请输入单链表长度:";
cin >> n;
CreateList(L, n);
ShowList(L);
cout << "请输入要查找的值:";
cin >> e;
FoundList(L, e);
cout << "请输入要插入的位置:";
cin >> a;
cout << "请输入要插入的值:";
cin >> b;
InsertList(L, a, b);
cout << "请输入要删除的位置:";
cin >> c;
DeleteList(L, c);
return 0;
}
bool InitList(LinkList& L)
{
L = new LNode;
L->next = NULL;
return true;
}
void CreateList(LinkList& L, int n) {
LinkList r, p;
L = new LNode;
L->next = NULL;
r = L;
cout << "请输入单链表:";
for (int i = 0; i < n; i++) {
p = new LNode;
cin >> p->data;
p->next = NULL;
r->next = p;
r = p;
}
}
void ShowList(LinkList L) {
LinkList p;
p = L->next;
cout << "单链表为:";
while (p) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
void FoundList(LinkList L, int e) {
LinkList p;
p = L->next;
int counts = 0;
while (p) {
if (p->data == e) {
counts++;
cout << "第" << counts << "次找到了与" << e << "相等的值" << endl;
}
p = p->next;
}
if (counts == 0) {
cout << "没有找到与" << e << "相等的值" << endl;
}
}
void InsertList(LinkList& L, int i, int e) {
LinkList p, s;
p = L;
int counts = 0;
while (p && (counts < i - 1)) {
p = p->next;
counts++;
}
s = new LNode;
s->data = e;
s->next = p->next;
p->next = s;
ShowList(L);
}
void DeleteList(LinkList& L, int i) {
LinkList s;
LinkList p = L;
int counts = 0;
while (p && (counts < i - 1)) {
p = p->next;
counts++;
}
s = p->next;
p->next = s->next;
delete s;
ShowList(L);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!