数据结构与算法-----顺序表(链表篇)

 目录

前言

顺序表

链表

概念

与数组的不同 

单链表

1. 创建节点

2.插入节点

尾插节点(形成链表结构)

向指定位置插入节点(链表已有)

​编辑

3.遍历链表数据

4.获取链表长度

5.删除节点

删除尾节点

删除指定节点

6.清空链表

7.链表的数据查找

8.链表的转置

 测试集

 环形链表

创建环形链表 

双向循环链表

创建双向循环链表


前言

        在此之前我们学习过了数组,数组也是一种顺序表,连续储存结构,但是数组本质上是一种静态空间,而我们主要讲的是动态空间的顺序表,顾名思义也就是我们常见的链表,链表又分为单链表以及环状链表双向循环链表,下面我们就一起来看看吧!(我已经上传代码,可下载代码资源)

顺序表

定义:

顺序表,全名顺序存储结构,是线性表的一种。通过《什么是线性表》一节的学习我们知道,线性表用于存储逻辑关系为“一对一”的数据,顺序表自然也不例外。
不仅如此,顺序表对数据的物理存储结构也有要求。顺序表存储数据时,会提前申请一整块足够大小的物理空间,然后将数据依次存储起来,存储时做到数据元素之间不留一丝缝隙。 

我们常见的顺序表有数组和链表等,前者是一个静态空间的数据储存结构,后者是一个动态空间数据储存结构。二者都可以去通过引索去实现表的操作,下面就看链表的相关操作。

链表

概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作。 

 链表的节点是分为两部分:数据域指针域

数据域:存放各种数据,比如int、char类型等等

指针域:作为指向下一个节点的桥梁 

typedef struct student{//数据域int index;//作为下标表示第几位long num;//学号char name[20];//名字int score;//分数//指针域struct student* next;//指向下一位的指针
}Student;

图解

 

与数组的不同 

单链表

  单链表是作为最简单的一种线性表的数据结构,通过动态空间分配可以实现单链表的创建,下面我们就学习单链表的创建以及增删改查等方法。

1. 创建节点

这里我们就不去按照之前学习链表时的做法了,之前我们是一次性去创建节点的同时还把节点连接起来,这里我们就把这两个步骤分开来做,让代码更加灵活。 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct date{long num;//学号char name[20];//名字int score;//分数
}Date;//存放数据
typedef struct student{//数据域Data x;//指针域struct student* next;//指向下一位的指针
}Student;//创建节点
Student* create_node(Date x) {Student* node = (Student*)malloc(sizeof(Student));//数据赋值node->x = x;//指针域指向空node->next = NULL;//返回这个节点return node;
}

2.插入节点

尾插节点(形成链表结构)

//把节点连接起来
void create_studentlist(Student**head,Date x) {Student* new_node = create_node(x);//如果头指针指向空节点的话,那么将头指针指向这个新的节点if (*head == NULL) {*head = new_node;}//如果头指针指向一个不为空的节点的话,那么就要顺着这个链表找到最后的节点,把新节点放入else {Student* move=*head;//创建一个移动节点,找到最后一个节点的位置while (move->next != NULL) {move = move->next;  //一直往后移}move->next = new_node;//把新节点放入进去}
}

向指定位置插入节点(链表已有)

//指定位置插入节点
void insert_node(Student** head, Student *new_node,int n) //向链表第n个位置插入节点
{Student* move=*head;//通过循环找到这个节点for (int i = 0; i < n; i++){move = move->next;}//下面这两步的顺序千万不能反过来!!!new_node->next = move->next;move->next = new_node;
}

3.遍历链表数据

//输出数据
void listprint(Student**head)
{Student* cur=*head;while (cur != NULL) {printf("%ld %s %d\n", cur->x.num, cur->x.name, cur->x.score);cur = cur->next;}printf("output over!");
}

4.获取链表长度

//获取链表长度
int get_listlength(Student**head)
{int length=0;Student* cur = *head;while (cur != NULL){length++;cur = cur->next;}return length;//返回长度的大小
}

5.删除节点

删除节点是链表的基本操作之一,分为删除尾节点和删除指定的节点(不是尾节点),这两种情况要去分类讨论,下面请看代码案例:

删除尾节点

//删除尾节点
void pop_lastnode(Student** head)
{//如果没有节点,就直接返回if (*head == NULL)return;//如果只有一个节点的话,就直接删除else if ((*head)->next == NULL){free(*head);*head = NULL;//重新置空}/*如果有多个节点的话,要找到最后一个节点的上一个节点,删除掉最后一个节点然后再把这个节点的next指向空*/else{Student* move = *head;while (move->next->next!=NULL){move = move->next;}free(move->next);move->next = NULL;}
}

删除指定节点

//删除指定节点
void pop_node(Student** head, int n)//删除第n个节点
{Student* move = *head;Student* p;//通过循环依次去找到要删除节点的上一个节点for (int i = 0; i < n-1; i++){move = move->next;}p = move->next;//此时要删除的节点标记为p节点move->next = p->next;//让p节点的上一个节点指向p节点的下一个节点,此时p节点已经断链free(p);
}

6.清空链表

//清空链表,释放全部的空间
void clear_list(Student**head){Student* cur=*head;Student* next;while (cur != NULL) {next = cur->next;free(cur);cur = next;}*head = NULL;//头指针置空printf("clear over!\n");
}

7.链表的数据查找

//数据查找//按学号查找
Student* list_search_num(Student** head, int num) {Student* cur = *head;while (cur!=NULL) {if (cur->x.num == num) { return cur; //找到了就返回这个节点}elsecur = cur->next;}printf("No find");return NULL;
}//按名字查找
Student* list_search_name(Student** head, char *name) {Student* cur = *head;while (cur != NULL) {if (strcmp(cur->x.name,name)==0) {return cur;   //找到了就返回这个节点}elsecur = cur->next;}printf("No find");return NULL;
}

8.链表的转置

我们已有的链表顺序是: 1->2->3->4->5  现在我想让这个链表顺序变为5->4->3->2->1(如下图所示)   这个过程就是链表的转置,我们可以去通过头插法去实现

头插法步骤如下: 

//链表的转置(头插法)
void list_reverse(Student** head) {Student *L, *start,* p, * q;//开辟一个暂存节点LL = (Student*)malloc(sizeof(Student));//初始化start = *head;L->next = start;p = L->next;L->next = NULL;while (p!= NULL) {q = p->next;p->next = L->next;L->next = p;p = q;}*head = L->next;//将此时的头结点等于新的头结点free(L);//释放掉暂存节点printf("reverse over!\n");
}

 测试集

//测试结果
int main()
{Date a[4] = { {1,"xiaoming",90} ,{ 2,"Jack",80 } ,{ 3,"Amy",98 } ,{ 4,"John",77 } };Student* head = NULL;//实例化一个头节点指针for (int i = 0; i < 4; i++) {//要把实例化的头指针的地址存入进去create_studentlist(&head, a[i]);//依次成链}listprint(&head);//输出数据printf("当前节点数量: %d\n", get_listlength(&head));list_reverse(&head);//逆转链表listprint(&head);//输出数据pop_lastnode(&head);//删除最后一个节点printf("当前节点数量: %d\n", get_listlength(&head));listprint(&head);//输出数据clear_list(&head);//清空链表printf("当前节点数量: %d\n", get_listlength(&head));}
//输出如下:
/*1 xiaoming 90
2 Jack 80
3 Amy 98
4 John 77
output over!
当前节点数量: 4
reverse over!
4 John 77
3 Amy 98
2 Jack 80
1 xiaoming 90
output over!
当前节点数量: 3
4 John 77
3 Amy 98
2 Jack 80
output over!
clear over!
当前节点数量: 0
*/

 环形链表

链表,从名字上来看是一条数据链,一般的链表其末尾节点是没有指向的,但当把链表的末尾节点指定为指向头节点时,则构成了一个环形链表。所以要想去建立一个环形链表只需要把最后一个节点重新指向头节点就行了,或者指向其他节点可以形成局部环形链表。下面我就讲讲通过代码去创建环形链表,相关操作方法(增删改查)跟上面所说的基本一样。

创建环形链表 

#include<stdio.h>
#include<stdlib.h>
typedef struct node {int date;struct node* next;
}Node;
//创建节点
Node *create_node(int date) {Node* node = (Node*)malloc(sizeof(Node));node->date = date;node->next = NULL;return node;
}
//把节点连起来
void create_annuallist(Node** head,int date) {Node* new_node = create_node(date);if (*head == NULL) {*head = new_node;}else{Node* cur = *head;while (cur->next) {cur = cur->next;}cur->next = new_node;}//成链//成环new_node->next = *head;
}

当你仔细细看的话,前面跟链表的创建基本上没什么区别,实际上就在最后面加上一个尾节点指向头节点就是了!

双向循环链表

带头双向循环链表是链表当中结构最复杂的链式结构,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个链表虽然结构复杂,但是使用代码实现以后会发现能带来很多优势。

创建双向循环链表

实现思路:

要想创建双向循环链表,就意味着在单相链表的基础上增加一个前指针来指向上一个节点,然后在成链的过程中后一个节点要指向前一个节点,前一个节点指向后一个节点,最后头尾节点互相指向就可以形成双向循环了。

代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//创建双向循环链表
typedef struct node {struct node* prev; //前指针char date[10];//数据域struct node* next; //后指针
}D_node;
D_node* create_D_node(char*date) {D_node* new_node = (D_node*)malloc(sizeof(D_node));strcpy(new_node->date, date);//前后指针都指向空,初始化new_node->prev = NULL;new_node->next = NULL;return new_node;
}
void create_D_list(D_node** head, char* date) {D_node* new_node = create_D_node(date);if (*head == NULL) {  //判断头结点是否为空*head = new_node;}else{D_node* cur = *head;while (cur->next) {cur = cur->next;}//双向指向(前指向后,后指向前)new_node->prev = cur;cur->next = new_node;}//头尾指针互相指向,成环new_node->next = *head;(*head)->prev = new_node;
}

 好了,以上就是本期的全部内容了,我们下一期再见!

分享一张壁纸:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/73999.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis的逆向工程

文章目录 前言MyBatis的逆向工程创建逆向工程的步骤添加依赖和插件创建MyBatis的核心配置文件创建逆向工程的配置文件执行MBG插件的generate目标 QBC查询增改 总结 前言 MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库表…

微信支付-Native支付(网页二维码扫码微信支付)简单示例

目录 概述 界面展示 & 前端代码&#xff08;Vue&#xff09; 后端实现&#xff08;SpringBoot&#xff09; Maven依赖 下单接口&#xff08;主要功能代码&#xff09; 支付成功回调接口 测试&#xff08;后端线上环境&#xff09; 概述 本篇博文主要演示和说明网页扫…

腾讯云新用户有哪些优惠政策和专属活动?

腾讯云作为中国领先的云计算服务提供商&#xff0c;一直在为用户提供优质、高效且具有竞争力的服务。对于新用户&#xff0c;腾讯云更是诚意满满&#xff0c;推出了一系列优惠政策和专属活动。本文将详细介绍腾讯云新用户的优惠政策和专属活动&#xff0c;帮助大家更好地了解如…

【算法专题突破】滑动窗口 - 长度最小的子数组(9)

目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后&#xff1a; 1. 题目解析 题目链接&#xff1a;209. 长度最小的子数组 - 力扣&#xff08;Leetcode&#xff09; 要注意的是&#xff0c;题目给的是正整数&#xff0c; 而题目要求并不难理解&#xff0c;就是找最短的…

Python批处理(一)提取txt中数据存入excel

Python批处理&#xff08;一&#xff09;提取txt中数据存入excel 问题描述 现从冠层分析软件中保存了叶面积指数分析的结果&#xff0c;然而软件保存格式为txt&#xff0c;且在不同的文件夹中&#xff0c;每个文件夹的txt文件数量不固定&#xff0c;但是txt文件格式固定。现需…

PPT 架构师三板斧

PPT 架构师三板斧 目录概述需求&#xff1a; 设计思路实现思路分析1.多节点上PPT 架构师三板斧2.几张框框组合有组织3.专业词汇4.切记点要点 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;ski…

Android扫码连接WIFI实现

0&#xff0c;目标 APP中实现扫WIFI分享码自动连接WIFI功能 1&#xff0c;前提条件 设备需要有个扫码器&#xff08;摄像头拍照识别也行&#xff09;&#xff0c;APP调用扫码器读取WIFI连接分享码。 2&#xff0c;增加权限 在AndroidManifest.xml中增加权限 <uses-permissi…

接入 NVIDIA A100、吞吐量提高 10 倍!Milvus GPU 版本使用指南

Milvus 2.3 正式支持 NVIDIA A100&#xff01; 作为为数不多的支持 GPU 的向量数据库产品&#xff0c;Milvus 2.3 在吞吐量和低延迟方面都带来了显著的变化&#xff0c;尤其是与此前的 CPU 版本相比&#xff0c;不仅吞吐量提高了 10 倍&#xff0c;还能将延迟控制在极低的水准。…

golang flag 包的使用指北

说起 golang 的 flag 个包&#xff0c;我们第一反应的是什么呢&#xff1f;至少我曾经第一次看到 flag 包的时候&#xff0c;第一反应是想起写 C 语言的时候咱们用于定义一个表示的&#xff0c;我们一般会命名为 flag 变量 实际上 golang 的 flag 包是用于处理命令行参数的工具…

pytorch-v2.0.1 cuda arm64 aarch64 torch 2.0.1+cu118 源码编译笔记【2】验证cuda安装 成功

接上篇 pytorch-v2.0.1 cuda arm64 aarch64 torch 2.0.1cu118 源码编译笔记_hkNaruto的博客-CSDN博客 由于采用/usr/local/bin/gcc编译&#xff0c;先设置LD_LIBRARY_PATH&#xff0c;再启动python3 export LD_LIBRARY_PATH/usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/…

TrOCR – 基于 Transformer 的 OCR 入门指南

多年来,光学字符识别 (OCR) 出现了多项创新。它对零售、医疗保健、银行和许多其他行业的影响是巨大的。尽管有着悠久的历史和多种最先进的模型,研究人员仍在不断创新。与深度学习的许多其他领域一样,OCR 也看到了变压器神经网络的重要性和影响。如今,我们拥有像TrOCR(Tran…

图论-01-图的基本表示-邻接矩阵和邻接表-Java

文章目录 邻接矩阵邻接表邻接表的问题和改进总结 邻接矩阵 import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner;public class AdjMatrix {private int V;private int E;private int[][] adj;// 构造函数&#xff0c;从文…

App线上网络问题优化策略

在我们App开发过程中&#xff0c;网络是必不可少的&#xff0c;几乎很难想到有哪些app是不需要网络传输的&#xff0c;所以网络问题一般都是线下难以复现&#xff0c;一旦到了用户手里就会碰到很多疑难杂症&#xff0c;所以对于网络的监控是必不可少的&#xff0c;针对用户常见…

鸿蒙系列-如何使用DevEco分析app的性能

如何使用DevEco分析app的性能 性能优化、启动优化、内存优化、FPS监测、性能分析&#x1f9d0; 在鸿蒙OpenHarmony开发过程中&#xff0c;开发者开发的代码&#xff08;Stage 模型&#xff09;通常以调用 ArkUI 框架的代码为主&#xff0c;主要优化的代码部分也在其中&#x…

使用GPU虚拟化技术搭建支持3D设计的职校学生机房(云教室)

背景 学校为职业学校&#xff0c;计算机教室需要进行Maya、Adobe Illustrator、Adobe Dreamweaver、Adobe PhotoShop等软件的教学。每个教室为35用户。资源需求为4核、8G内存、80G硬盘。 基于桌面虚拟化VDI技术的机房在成本、可管理性方面&#xff0c;相对于传统胖终端的机房…

华为认证系统学习大纲及课程

前言 任何学习过程都需要一个科学合理的学习路线&#xff0c;才能够有条不紊的完成我们的学习目标。华为认证网络工程师所需学习的内容纷繁复杂&#xff0c;难度较大&#xff0c;所以今天特别为大家整理了一个全面的华为认证网络工程师学习大纲及课程&#xff0c;帮大家理清思…

更健康舒适更科技的照明体验!书客SKY护眼台灯SUKER L1上手体验

低价又好用的护眼台灯是多数人的需求&#xff0c;很多人只追求功能性护眼台灯&#xff0c;显色高、无频闪、无蓝光等基础需求。但是在较低价格中很难面面俱到&#xff0c;然而刚发布的SUKER书客L1护眼台灯却是一款不可多得的性价比护眼台灯&#xff0c;拥有高品质光源&#xff…

前端实现展开收起的效果 (react)

需求背景&#xff1a;需要实现文本的展开收起效果&#xff0c;文本是一行一行的&#xff0c;数据格式是数组结构。 如图所示&#xff08;图片已脱敏&#xff09; 简单实现&#xff1a;使用一个变量控制展开收起效果。 展开收起逻辑部分&#xff08;react&#xff09; const […

国际版腾讯云阿里云免费开户:全站加快 DCDN 重磅发布!打造新一代加快引擎

腾讯云全站加快 DCDN 重磅发布&#xff01;打造新一代加快引擎 在数字化转型革新逐渐深化的当下&#xff0c;安全高效成为企业上云、全球化布置的要害需求。 跟着运用场景复杂度不断提高、事务需求差异化开展&#xff0c;为了给企业供给更完善的安全加快服务&#xff0c;阿里云…

【Linux】VirtualBox安装Centos7

文章目录 下载并安装VirtualBox下载Centos镜像VirtualBox设置管理->全局设定&#xff1a;设定虚拟机默认安装路径工具->网络管理器&#xff1a;添加NetWork网络配置 VirtualBox安装CentOS7新建虚拟机&#xff0c;指定安装目录及名称&#xff0c;点击下一步指定虚拟机内存…