当前位置: 首页 > news >正文

数据结构day02(链表)

【1】链表 Link list

链表又称单链表/链式存储结构,用于存储逻辑关系为“一对一”的数据

和顺序表不同,使用链表存储数据,不强制要求在内存中集中存储,各个元素可以分散存储在内存中。

所以在链表中,每个数据元素可以配有一个指针用于找到下一个元素即节点,这意味着,链表上的每个“元素”都如下图

 

 链表的特性

逻辑结构:线性结构

存储结构:链式存储

特点:内存不连续,需要通过指针链接,大小不固定,解决顺序表插入删除麻烦的问题

操作:增删查改

struct node
{
int data;                      //数据域,用于存储数据
struct node * next;            //指针域,用于存储下一个节点的地址
};

单项链表

有头链表:存在一个头结点,头节点的数据域无效,指针域有效

无头链表:每一个节点的数据域和指针域都有效

 遍历无头单向链表

 

#include <stdio.h>
#include <stdlib.h>
typedef char datatype; // 重定义字符类型
typedef struct node
{datatype data;     // 数据用来存数据struct node *next; // 指针域用来存下一个节点的地址
} Node_t, *Node_p;     // 重定义结构体数据类型,和结构体指针类型/*遍历无头单项链表*/int main(int argc, char const *argv[]){//定义4个节点并赋值Node_t A = {'a',NULL};Node_t B = {'b',NULL};Node_t C = {'c',NULL};Node_t D = {'d',NULL};//连接4个节点A.next = &B;B.next = &C;C.next = &D;//定义一个头指针指向第一个节点Node_p p = &A;//通过指针遍历无头单项链表while(p != NULL){printf("%c ",p->data);//打印每个节点数据域中的值p = p->next;//让p指向下一个节点}printf("\n");return 0;}

遍历有头单向链表

 

#include <stdio.h>
#include <stdlib.h>
typedef char datatype; // 重定义字符类型
typedef struct node
{datatype data;     // 数据用来存数据struct node *next; // 指针域用来存下一个节点的地址
} Node_t, *Node_p;     // 重定义结构体数据类型,和结构体指针类型
/*遍历有头单项链表*/int main(int argc, char const *argv[]){// 定义4个节点并附值Node_t A = {'a', NULL};Node_t B = {'b', NULL};Node_t C = {'c', NULL};Node_t D = {'d', NULL};// 连接4个节点A.next = &B;B.next = &C;C.next = &D;// 定义头节点,数据域无效,指针域有效Node_t H = {'\0', &A};// 定义一个头指针,指向头节点Node_p p = &H;#if 0 //条件编译p = p->next; // 先跨越头节点,指向第一个数据域有效的节点Awhile (p != NULL) //当前指针不是空{printf("%c ", p->data);//打印数据域内容p = p->next;//指向下一个节点}printf("\n");#elsewhile (p->next != NULL)//当前指针的指针域内数据是否为空{p = p->next;printf("%c ",p->data);}printf("\n");#endifreturn 0;}

 

 链表尾插法

写一个有头单向链表,用于保存输入的学生成绩,实现一输入学生成绩就创建一个新的节点,将成绩保存起来。再将该节点链接到链表的尾,直到输入-1结束。

要求:每个链表的节点由动态内存分配得到 , 也就是用malloc。

过程:

  1. malloc申请空间link_node_t大小作为头节点
  2. 将新节点放到链表尾部

 

 

#include <stdio.h>
#include <stdlib.h>
typedef char datatype; // 重定义字符类型
typedef struct node
{datatype data;     // 数据用来存数据struct node *next; // 指针域用来存下一个节点的地址
} Node_t, *Node_p;     // 重定义结构体数据类型,和结构体指针类型
/*链表尾插法*/int main(int argc, char const *argv[]){Node_p p_new = NULL;  // 先定义一个结构体指针,置空待用Node_p p_tail = NULL; // 先定义一个结构体指针,置空待用int score = -1;            // 定义一个变量存放成绩// 创建一个头节点,用头指针p指向头节点Node_p H = (Node_p)malloc(sizeof(Node_t));//malloc开辟堆区空间if (NULL == H)//判断堆区空间是否开辟成功{printf("malloc lost");}H->next = NULL;//头节点指针域置空p_tail = H;//让尾指针指向头节点//循环输入学生成绩直到-1结束,创建新节点存放学生成绩,尾插的链表中while(1)//循环输入成绩{scanf("%d",&score);if(score == -1)//结束条件{break;}p_new = (Node_p)malloc(sizeof(Node_t));//创建新节点,用来存放学生成绩if(NULL == p_new)//判断堆区空间是否开辟成功{printf("malloc error");}//初始化新节点,把成绩赋值到数据域,指针域置空p_new->data = score;p_new->next = NULL;p_tail->next = p_new;//将新节点连接到当前尾节点,作为新的尾节点,就是把新节点的地址存放到当前尾节点的指针域中p_tail = p_new;//将当前尾节点移动到新节点上,是新节点成为尾节点,尾指针永远指向最后一个节点}//遍历链表while(H->next != NULL){H = H->next;printf("%d ",H->data);}printf("\n");return 0;}

 有头单向链表的函数操作

 


#include <stdio.h>
#include <stdlib.h>
typedef char datatype; // 重定义字符类型
typedef struct node
{datatype data;     // 数据用来存数据struct node *next; // 指针域用来存下一个节点的地址
} Node_t, *Node_p;     // 重定义结构体数据类型,和结构体指针类型/*有头单向链表的函数操作*/
/*创建一个空的单向链表*/
Node_p Create()
{Node_p p = (Node_p)malloc(sizeof(Node_t)); // 开辟一个节点大小的堆区空间if (NULL == p)                             // 开辟失败{printf("malloc lost");return NULL;}p->next = NULL; // 初始化头节点指针域return p;       // 开辟成功,返回
}/*计算链表的长度*/
int length(Node_p p)
{int len = 0;            // 定义一个变量来表示长度,并赋初始值为0while (p->next != NULL) // 当指针域不等于NULL就说明没到最后一个节点{p = p->next; // 指针向下一个节点移动len++;       // 长度加加}return len; // 返回长度值
}/*向项链表中插入数据*/
void Insert(Node_p p, int post, int data)
// p 保存链表的头指针   post 要插入的位置   data  要插入的数据
{// 容错判断if (post < 0 || post > length(p)) // 插入位置小于0或大于链表长度{printf("post error");}Node_p p_new = NULL;           // 创建一个指针,置空备用,用来存放要插入的新数据for (int i = 0; i < post; i++) // for循环遍历到要查如位置前的那该个节点p = p->next;p_new = (Node_p)malloc(sizeof(Node_t)); // 开辟一个节点大小堆区空间存放新数据if (NULL == p_new){printf("malloc lost");}p_new->data = data; // 在数据域存放要查入的数据p_new->next = NULL; // 初始化为NULL;// 链接新节点时,要先连后面,再连前面(否则,先连前面后面的地址就找不到了)p_new->next = p->next; // 让新节点链接到要插入的位置节点上p->next = p_new;       // 让要插入位置前的那个节点连接到新的节点上
}/*修改链表的内容*/
void Modify(Node_p p, int post, int data)
// p 保存链表的头指针  post  要修改的数据位置  data   要修改成的数据
{// 容错判断if (post < 0 || post > length(p)){printf("error\n");}for (int i = 0; i < post; i++) // for循环遍历到要插入位置前的那该个节点p = p->next;Node_p mod = p->next; // 定义一个指针指向要插入位置的节点mod->data = data;     // 修改要修改的值
}/*删除链表的内容*/
void Delete(Node_p p, int post)
// p 保存链表的头指针  post  要删除的数据位置
{// 容错判断if (post < 0 || post > length(p)){printf("delete error\n");}for (int i = 0; i < post; i++)p = p->next;Node_p p_del; // 定义一个指针指向要删除的节点p_del = p->next;p->next = p_del->next; // 让被删除的节点前的那个节点链接到被删除的那个节点后的节点free(p_del);           // 释放被删除的那个节点p_del = NULL;          // 将指向被删除的那个节点的指针置空
}/*查找链表中的内容*/
int Serarch(Node_p p, int post)
// p 保存链表的头指针  post  要查询的数据位置
{// 容错判断if (post < 0 || post > length(p)){printf("error\n");return -1;}for (int i = 0; i < post; i++)p = p->next;Node_p ser = p->next; // 定义一个指针指向要查询的节点return ser->data;     // 返回查询的节点数据域中的内容
}
/*遍历链表*/
void show(Node_p p)
// p 保存链表的头指针
{while (p->next != NULL){p = p->next;printf("%d ", p->data);  }printf("\n");
}int main(int argc, char const *argv[])
{Node_p H = Create();for (int i = 0; i < 5; i++) // 循环调用插入函数Insert(H, i, i);printf("插入后:\n");show(H);// Insert(H, -1, 6);Delete(H, 4);printf("删除后:\n");show(H);Modify(H, 1, 100);printf("修改后:\n");show(H);int data = Serarch(H, 1);printf("查询的数据:\n");printf("%d\n", data);return 0;
}

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • luckyexcel 编辑预览excel文件
  • 【机器学习第9章——聚类】
  • elasticsearch 字段类型的索引、字段类型修改、字段类型、分页、排序、分组、聚合
  • Java+vue3+element-plus+ts上传图片到服务器并返回图片可访问链接
  • 关于SOA和微服务
  • docker swarm如何让两个副本分别跑在两台不同的主机上
  • ubuntu 24.04 软件源配置,替换为国内源
  • 【GitLab】使用 Docker 安装 GitLab:配置 SSH 端口
  • 数据守护者:SQL一致性检查的艺术与实践
  • dev c++中,在C++11模式下编译带M_PI宏的文件报错的解决办法
  • es查看与删除索引
  • LVGL在方形屏幕上的参考案例
  • Python爬虫——爬取某网站的视频
  • 【python学习】如何利用threading 库提升性能:深入解析与实战应用 模拟温格高的环法冠军之路
  • 数据维度的魔法:SQL多维数据模型的构建与操作
  • ERLANG 网工修炼笔记 ---- UDP
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • JavaScript HTML DOM
  • java第三方包学习之lombok
  • laravel 用artisan创建自己的模板
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • Solarized Scheme
  • SpringBoot 实战 (三) | 配置文件详解
  • 百度地图API标注+时间轴组件
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 蓝海存储开关机注意事项总结
  • 聊一聊前端的监控
  • 异常机制详解
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $forceUpdate()函数
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (Charles)如何抓取手机http的报文
  • (Forward) Music Player: From UI Proposal to Code
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (第一天)包装对象、作用域、创建对象
  • (二)springcloud实战之config配置中心
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)平衡树
  • (转)项目管理杂谈-我所期望的新人
  • ***通过什么方式***网吧
  • .NET 5种线程安全集合
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net 简单实现MD5
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)
  • .NET学习全景图
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [C#]OpenCvSharp使用帧差法或者三帧差法检测移动物体