首页 > 其他分享 >线性表的链接储存结构及实现

线性表的链接储存结构及实现

时间:2023-02-03 11:06:15浏览次数:47  
标签:Node 结点 单链 线性表 int 储存 next 链接 first


单链表

1 单链表的定义

单链表是用一组任意的存储单元来存放线性表的元素。存储单元可以连续,也可以不连续

为了正确的表示元素之间的逻辑关系,每个存储单元除了存储元素外 ,还需要存储后继元素的位置,这个地址信息用指针表示,称为指针;这两个元素组成了数据元素的存储映像,称为结点
也就是说节点有两个部分组成的

  1. 数据域
  2. 指针域

线性表的链接储存结构及实现_头结点

2 单链表结点c++实现

struct  Node{  //Node  可以自己随便起名
int data;//这是数据域
Node *next;//这是指针域
}

3 单链表的构造

为了避免其他对单链表的操作造成的bug,我们需要在构造单链表的时候构建一个头结点
怎么理解这个头结点呢,我是这么理解的就是不给他的数据域赋值,同时其他的操作不针对头结点,仅仅是个标识

插入某个节点

线性表的链接储存结构及实现_链表_02

删除某个节点

线性表的链接储存结构及实现_链表_03

CODE:

struct Node{
int data;
Node *next;
};

class LinkList{
public:
LinkList(){
first = new Node; //申请一个Node类型的结点/存储空间
//因为是作为头结点,所以不需要给数据域赋值
first->next = NULL; //建立一个只有头结点的空链表 所以next指向NULL
}

//头插法给链表赋初值
LinkList(int a[],int n){ //数组形参数作为给单链表赋值
first = new Node;
first->next = NULL; //立一个只有头结点的空链表
for(int i = 0;i < n;i++ ){
Node *s = new Node;
s->data = a[i]; //赋值
s->next = first->next; //每个新建的结点都要链接之前头结点所指向的结点
first->next = s; //头插法,每个元素结点都插在头结点后
}
}

//尾插法给单链表赋初值
void AddFromLast(int a[],int n){
Node *p = first; //设立工作指针,使他始终指向单链表的尾部
for(int i = 0;i < n;i++){
Node *s = new Node; //申请新的结点
p->next = s; //原链表的尾部next指针执行新的结点
s->data = a[i]; //赋值
p = s; //尾指针后移
}
p->next = NULL; //尾指针的next指向空
}

void AddData(int a,int position){
Node *s =new Node; //申请Node类型的空间
Node *p; //工作指针
p = first;
s->data = a;
int count = 0;
//下面这个循环的结果就是工作指针p指向了第position-1个结点
while(count != position-1){
p = p->next;
count++;
}
//开始执行插入
s->next = p->next; //先让s->next值向第position 个结点,顺序不能乱
p->next = s; //第position-1个结点的next指向新添加的结点
//给结点赋值
s->data = a;
}

//析构函数 单链表的空间是用new申请的,只能用delete删除
~LinkList(){

while(first->next != NULL){
Node *p = first;
first = first->next;
delete p;
}
}

//删除指定的结点
int DeleteData(int i){
Node *p = first;
Node *r;
int count = 0;
while(count != i-1){
p = p->next;
count++;
}
r = p->next;
p->next = r->next;
int x = r->data;
delete r;
return x;
}

//遍历所有的数据
void ShowAll(){
Node *p =first->next;
while(p != NULL){
cout<<p->data<<endl;
p = p->next;
}
}

//按位查找
int SelectByPosition(int position){
Node *p = first;
int count = 0;
while(count != position){
p = p->next;
count++;
}
return p->data;
}

private:
Node *first;//头指针
};

int main(){

int a[10] = {1,2,3,4,5,6,7,8,9,0};
LinkList link(a,10);
link.ShowAll();
cout<<endl;
link.AddData(111,5);
link.ShowAll();
cout<<endl;
link.DeleteData(5);
link.ShowAll();
cout<<endl;
link.AddFromLast(a,10);
link.ShowAll();
cout<<endl;

cout<<link.SelectByPosition(5);
cout<<endl;

}

单向链表结构与顺序存储结构的优缺点

顺序存储结构用一段连续的存储单元依次存储线性表的数据元素。

查找:顺序存储结构O(1),单链表O(n)。

插入和删除:顺序存储结构O(n),单链表O(1)。

顺序存储结构需要预先分配存储空间,分大了浪费空间,分小了容易造成内存溢出;单链表不需要分配存储空间,只要有就可以分配,元素个数也不受限制。

循环链表

单链表有一定的缺陷,就是单向性,只能从一个结点到下一个节点,而不能访问到上一个结点,而循环链表就可以解决这一问题,当然,用双向链表更加方便

Code:

struct node
{
int data;
struct node *next;//指针域
int size;//循环链表的长度
}node,*linklist;//linklist为定义的指针结构体变量

void create_list_head(linklist *l)//头插法建立循环链表
{
int i,j,x;
linklist p,q;
printf("please input length");
scanf("%d",&j);
(*l)=(node*)malloc(sizeof(node));
(*l)->next=NULL;//必须定义,缺少error
(*l)->size=j;
for(i=0;i<j;i++)//头插法输入数据
{
scanf("%d",&x);
p=(node*)malloc(sizeof(node));
p->data=x;
p->next=(*l)->next;
(*l)->next=p;
}
//q=(node*)malloc(sizeof(node));
q=(*l)->next;
while(q->next!=NULL)//找到最后一个结点
{
q=q->next;
}
//printf("%d",q->data);
q->next=(*l)->next;//将最后一个结点指向第一个结点



}

void create_list_tail(linklist *l)//尾插法建立循环链表
{
int i,j,x;
linklist p,r,t;
printf("please input the length");
scanf("%d",&j);
(*l)=(node*)malloc(sizeof(node));
(*l)->next=NULL;
(*l)->size=j;
t=(*l);
for(i=0;i<j;i++)
{
scanf("%d",&x);
p=(node*)malloc(sizeof(node));
p->data=x;
t->next=p;
t=p;//每新建一个结点在结束时都为最后一个结点,下一个节点在这个结点后面插入

}
t->next=NULL;
r=(*l)->next;
while(r->next!=NULL)
{
r=r->next;
}
r->next=(*l)->next;
}

void print_list_he(linklist *l)//打印输出
{
int i;
linklist p;
p=(*l)->next;
for(i=0;i<(*l)->size;i++)
{
printf("%d\n",p->data);
p=p->next;
}
}

int main()
{
linklist a;
create_list_head(&a);
create_list_tail(&a);
print_list_he(&a);
return 0;
}

 

标签:Node,结点,单链,线性表,int,储存,next,链接,first
From: https://blog.51cto.com/u_15952369/6035570

相关文章

  • C/C++编译链接
    一、编译链接过程名词解释编译:由编译器对各个源文件进行词法分析、语法分析、语义分析等操作,最终生成多个目标文件。由于这些文件可能存在互相调用对方的函数或变量,还......
  • Linux基础:文件相关信息、文件索引信息、链接信息、系统时间、机器克隆、定时任务、par
    目录一、文件相关信息二、文件索引信息三、链接信息四、系统时间五、机器克隆六、定时任务七、paramiko模块八、公钥私钥九、paramiko其他操作十、代码封装十一、面试题回......
  • esp32链接手机通信
    测试通过#include<WiFi.h>constchar*ssid="@*****";constchar*password="******";//这里是第三方wifi的名称和密码,本机作为sta接入constIPAddressserv......
  • 检查Chrome收藏夹链接是否有效
    检查Chrome浏览器标签,通过Chrome导出的收藏夹文件,挨个使用httpget请求检查url是否有效packagemainimport( "bufio" "errors" "flag" "fmt" "io" "net" "net/h......
  • VisualVM 远程链接
    在启动参数上添加一下参数-Dcom.sun.management.jmxremote.port=8999(jmx连接端口号)-Dcom.sun.management.jmxremote.rmi.port=8999-Dcom.sun.management.jmxremote......
  • gcc后续——链接时的静态库和动态库
    本篇文章是链接阶段静动态库的理解,</font>​​点击查看gcc四个阶段​​@TOC1.库库:分为静态库和动态库(本质也是文件)静态库:libXXXX.a动态库:libXXXX.so检测linux所用库......
  • 路径和超链接
    相对路径:以引用文件所在位置为参考基础,而建立出的目录路径,图片相对于HTML页面的位置绝对路径:指目录下的绝对位置,直接到达目标位置,通常从盘符开始的路径.超链接标签......
  • Linux设置动态链接库so的默认搜索路径
    众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib,64位系统是/lib64和/usr/lib64。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该动态库......
  • 【阿里云ACP】-02(弹性储存、对象储存OSS)
    弹性网卡弹性网卡:是一种可以附加到专有网络VPC类型ECS实例上的虚拟网卡。通过弹性网卡,您可以在任何阿里云地域下实现高可用集群搭建、低成本故障转移和精细化的网络管理......
  • linux服务器运行java项目, 监控查看内存、储存空间和cpu占用率
    服务器部署方式为tomcat中运行war包的方式,有一次重新部署时候发现报异常堆栈溢出了.想要定位到某个war包中通过学习整理出此篇文章以作记录笔记.1.关于内存过高......