嵌入式学习-线性表Day05-双向链表

嵌入式学习-线性表Day05-双向链表

双向链表

操作函数

1)创建一个空的双向链表

2)双向链表中间插入

3)双向链表尾插

4)双线链表中间删除

5)双线链表删除最后一个节点

双向循环链表

双向链表

//双向链表的节点定义

typedef int datatype;

typedef struct node_t

{

datatype data;//数据域

struct node_t *next;//指向下一个节点的指针 next 下一个

struct node_t *prior;//指向前一个节点的指针 prior 先前的

}link_node_t,*link_list_t;

//将双向链表的头指针和尾指针封装到一个节点体里

//思想上有点像学的链式队列

typedef struct doublelinklist

{

link_list_t head; //指向双向链表的头指针

link_list_t tail; //指向双向链表的尾指针

int len; //用来保存当前双向链表的长度

}double_node_t,*double_list_t;

操作函数

1)创建一个空的双向链表

2)双向链表中间插入

​​​​​​​3)双向链表尾插

4)双线链表中间删除

5)双线链表删除最后一个节点

#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node_t
{
    datatype data;        // 数据域
    struct node_t *next;  // 指向下一个节点的指针 next 下一个
    struct node_t *prior; // 指向前一个节点的指针 prior 前一个
} link_node_t, *link_list_t;// 将双向链表的头指针和尾指针封装到一个结构体里
// 思想上有点像学的链式队列
typedef struct doublelinklist
{
    link_list_t head; // 指向双向链表的头指针
    link_list_t tail; // 指向双向链表的尾指针
    int len;
} double_node_t, *double_list_t;
// 1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList()
{// 1.开辟存放头尾指针结构体的空间
    double_list_t p = (double_list_t)malloc(sizeof(double_node_t));
    if (p == NULL){perror("createEmptyDoubleLinkList err");
        return NULL;}// 2.初始化(开辟头节点的空间)
    p->len = 0;
    p->tail = p->head = (link_list_t)malloc(sizeof(link_node_t));
    if (p->tail == NULL){perror("p->tail malloc err");
        return NULL;}// 3.初始化头节点
    p->tail->next = NULL;
    p->tail->prior = NULL;
    return p;
}
// 2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data)
{// 0.容错判断
    if (post < 0 || post > p->len){perror("insertIntoDoubleLinkList err");
        return -1;}// 1.开辟一个新节点存放数据,初始化
    link_list_t pnew = (link_list_t)malloc(sizeof(link_node_t));
    if (pnew == NULL){perror("pnew malloc err");
        return -1;}
    pnew->data = data;
    pnew->prior = NULL;
    pnew->next = NULL;// 2.将新节点插入链表// 分两种情况// 尾插
    if (post == p->len){
        p->tail->next = pnew;
        pnew->prior = p->tail;
        p->tail = pnew; // 移动尾指针}
    else // 中间插入{// 1)temp指针指向被插入位置
        link_list_t temp = NULL;
        if (post < p->len / 2) // 前半段(从前向后移动){
            temp = p->head;
            for (int i = 0; i <= post; i++)
                temp = temp->next;}
        else // 后半段(从后向前移动){
            temp = p->tail;
            for (int i = 0; i < p->len - 1 - post; i++)
                temp = temp->prior;}// 2)进行插入操作(先连前面,再连后面)
        temp->prior->next = pnew;
        pnew->prior = temp->prior;
        temp->prior = pnew;
        pnew->next = temp;}// 链表长度+1
    p->len++;
    return 0;
}
// 3.遍历双向链表
void showDoubleLinkList(double_list_t p)
{printf("正向遍历:");
    link_list_t temp = p->head;
    while (temp->next != NULL){
        temp = temp->next;printf("%d  ", temp->data);}printf("\n-------------------\n");printf("反向遍历:");
    temp = p->tail;
    while (temp != p->head){printf("%d  ", temp->data);
        temp = temp->prior;}printf("\n-------------------\n\n");
}
// 5.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p)
{
    return p->len == 0;
}
// 4.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post)
{// 1.容错判断
    if (post < 0 || post >= p->len || isEmptyDoubleLinkList(p)){perror("deletePostDoubleLinkList err");
        return -1;}// 2.对删除位置进行判断
    if (post == p->len - 1) // 尾删{
        p->tail = p->tail->prior; // 向前移动尾指针free(p->tail->next);      // 释放被删除节点
        p->tail->next = NULL;}
    else // 中间删{// 1)将temp移动到被删除位置
        link_list_t temp = NULL;
        if (post < p->len / 2) // 前半段{
            temp = p->head;
            for (int i = 0; i <= post; i++)
                temp = temp->next;}
        else // 后半段{
            temp = p->tail;
            for (int i = 0; i < p->len - 1 - post; i++)
                temp = temp->prior;}// 2)进行删除操作
        temp->prior->next = temp->next;
        temp->next->prior = temp->prior;free(temp);
        temp = NULL;}// 链表长度-1
    p->len--;
    return 0;
}
// 6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p)
{
    return p->len;
}
// 7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p, datatype data)
{
    link_list_t h = p->head;
    int post = 0;
    while (h->next != NULL){
        h = h->next;
        if (h->data == data)
            return post;
        post++;}
    return -1;
}
// 8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p, int post, datatype data)
{// 1.容错判断
    if (post < 0 || post >= p->len){perror("changeDataDoubleLinkList err");
        return -1;}// 2.将temp移动到被修改位置
    link_list_t temp = NULL;
    if (post < p->len / 2) // 前半段{
        temp = p->head;
        for (int i = 0; i <= post; i++)
            temp = temp->next;}
    else // 后半段{
        temp = p->tail;for(int i=0;i<p->len-1-post;i++)
            temp=temp->prior;}// 3.修改数据
    temp->data = data;
    return 0;
}
// 9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data)
{
    link_list_t h = p->head->next;
    link_list_t pdel = NULL;//1.遍历无头单向链表
    while (h!= NULL){if(h->data == data) //删除{if(h == p->tail)//尾删{
                p->tail = p->tail->prior;free(p->tail->next);
                p->tail->next=NULL;
                h = NULL;//结束遍历}
            else//中间删除{
                h->prior->next = h->next;
                h->next->prior = h->prior;
                pdel = h;
                h = h->next;//继续遍历free(pdel);
                pdel = NULL;}
            p->len--;//长度-1}
        else//不删除
            h=h->next;}
    return 0;
}
int main(int argc, char const *argv[])
{
    double_list_t p = createEmptyDoubleLinkList();
    for (int i = 1; i <= 5; i++)insertIntoDoubleLinkList(p, i - 1, i);showDoubleLinkList(p); // 1 2 3 4 5insertIntoDoubleLinkList(p, 1, 200);showDoubleLinkList(p); // 1 200 2 3 4 5deletePostDoubleLinkList(p, 2);showDoubleLinkList(p);                                            // 1 200 3 4 5printf("%d post is %d\n", 200, searchPostDoubleLinkList(p, 200)); // 1changeDataDoubleLinkList(p,1,300);showDoubleLinkList(p);//1 300 3 4 5deleteDataDoubleLinkList(p,300);showDoubleLinkList(p);//1 3 4 5
    while (!isEmptyDoubleLinkList(p)){deletePostDoubleLinkList(p, 0);}free(p->head);
    p->head = NULL;free(p);
    p = NULL;    return 0;
}

双向循环链表

双向循环链表	解决约瑟夫问题
#include <stdio.h>
#include <stdlib.h>typedef int datatype;
typedef struct node_t
{
	datatype data;struct node_t * prior;struct node_t * next;
}link_node_t,*link_list_t;typedef struct doublelinklist
{
	link_list_t head;
	link_list_t tail;
}double_node_t,*double_list_t;int main(int argc, const char *argv[])
{int i;int all_num = 8;//猴子总数int start_num = 3;//从3号猴子开始数int kill_num = 3;//数到几杀死猴子 
	link_list_t h = NULL;
	link_list_t pdel = NULL;//用来指向被杀死猴子的节点printf("请您输入猴子的总数,开始号码,出局号码:\n");scanf("%d%d%d",&all_num,&start_num,&kill_num);//1.创建一个双向的循环链表
	double_list_t p = (double_list_t)malloc(sizeof(double_node_t));//申请头指针和尾指针if(NULL == p){perror("malloc failed");return -1;}
	p->head = p->tail = (link_list_t)malloc(sizeof(link_node_t));if(NULL == p->tail){perror("p->tail malloc failed");return -1;}
	p->head->data = 1;
	p->head->prior = NULL;
	p->head->next = NULL;//将创建n个新的节点,链接到链表的尾for(i = 2; i <= all_num; i++){
		link_list_t pnew = (link_list_t)malloc(sizeof(link_node_t));if(NULL == pnew){perror("pnew malloc failed");return -1;}
		pnew->data = i;
		pnew->prior = NULL;
		pnew->next = NULL;//(1)将新的节点链接到链表的尾
		p->tail->next = pnew;
		pnew->prior = p->tail;//(2)尾指针向后移动,指向当前链表的尾
		p->tail = pnew;}//(3)形成双向循环链表 
	p->tail->next = p->head;
	p->head->prior = p->tail;//调试程序 
#if 0while(1){printf("%d\n",p->head->data);
		p->head = p->head->next;sleep(1);}
#endif//2.循环进行杀死猴子
	h = p->head;//(1)先将h移动到start_num处,也就是开始数数的猴子号码处for(i = 0; i < start_num-1; i++)
		h = h->next;while(h->next != h)//当h->next == h 就剩一个节点了,循环结束{//(2)将h移动到即将杀死猴子号码的位置for(i = 0; i < kill_num-1; i++)
			h = h->next;//(3)进行杀死猴子,经过上面的循环后,此时的h指向即将杀死的猴子
		h->prior->next = h->next;
		h->next->prior = h->prior;
		pdel = h;//pdel指向被杀死猴子的位置printf("kill is -------%d\n",pdel->data);
		h = h->next;//需要移动,从杀死猴子后的下一个位置开始数free(pdel);}printf("猴王是%d\n",h->data);return 0;
}	

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

力扣题11~20

题11&#xff08;中等&#xff09;&#xff1a; 思路&#xff1a; 这种题目第一眼就是双循环&#xff0c;但是肯定不行滴&#xff0c;o(n^2)这种肯定超时&#xff0c;很难接受。 所以要另辟蹊径&#xff0c;我们先用俩指针&#xff08;标志位&#xff09;在最左端和最右端&am…

补图、同构图、自补图是什么意思

补图、同构图、自补图的解释网上很多文章写的不是很明确&#xff0c;所以我写一段小笔记记录一下。 同构图 同构图的数学定义为&#xff1a;给定两个图G(V,E)和G(V,E)&#xff0c;若存在一个双射函数f:V->V&#xff0c;使得对于任意的顶点u,v∈V&#xff0c;(u,v)∈E当且仅…

日语学习零基础生活日语口语柯桥外语学校|股票用日语怎么说?

在日语中&#xff0c;“股票”可以说&#xff1a; • 株&#xff08;かぶ&#xff09; 这是最常用的表达方式&#xff0c;直接表示“股票”。 例如&#xff1a; 株を買う - 买股票 株を売る - 卖股票 • 株式&#xff08;かぶしき&#xff09; 这个词也是“股票”的意…

回答网友的一个问题socket_server的问题

今天网上有人讨论在Midas数据库编程中&#xff0c;如果客户端采用Socket连接&#xff0c;服务端运行Borland Socket Server程序&#xff0c;在服务器&#xff08;一个CPU以上&#xff09;上运行有问题。俺就找出了这个&#xff1a;

【工具使用】使用Docsify搭建个人文档网站

检查Node.js安装状态 首先&#xff0c;打开命令提示符&#xff08;CMD&#xff09;&#xff0c;输入以下命令以验证Node.js是否已经安装在您的电脑上&#xff1a; node -v安装Docsify CLI工具 接下来&#xff0c;通过以下命令全局安装Docsify的命令行工具&#xff1a; npm …

布隆过滤器(Bloom Filter)详解

一、引言 在处理大量数据的场景中&#xff0c;我们经常会遇到判断一个元素是否在某个集合中的问题。传统的方法可能是使用 HashMap 等集合将数据保存起来&#xff0c;然后进行比较确定&#xff0c;但在元素很多的情况下&#xff0c;这种方式会非常浪费空间&#xff0c;检索速度…

知识蒸馏介绍

一、知识蒸馏介绍 1.1 概念介绍 知识蒸馏&#xff08;knowledge distillation&#xff09;是模型压缩的一种常用的方法&#xff0c;不同于模型压缩中的剪枝和量化&#xff0c;知识蒸馏是通过构建一个轻量化的小模型&#xff0c;利用性能更好的大模型的监督信息&#xff0c;来…

极客兔兔Gee-Cache Day7

protobuf配置&#xff1a; 从 Protobuf Releases 下载最先版本的发布包安装。解压后将解压路径下的 bin 目录 加入到环境变量即可。 如果能正常显示版本&#xff0c;则表示安装成功。 $ protoc --version libprotoc 3.11.2在Golang中使用protobuf&#xff0c;还需要protoc-g…

高效编辑修改文本文档:批量修改文本文档中的特定词汇

在处理大量文本文档时&#xff0c;经常需要批量修改文章的内容&#xff0c;特别是当多个文档里的内容&#xff0c;手动逐个修改不仅效率低下&#xff0c;还容易出错。因此&#xff0c;掌握一些批量修改文本文档内容的技巧变得尤为重要。本文将介绍几种高效编辑文章的方法&#…

基于IMX6UL的EPIT的定时器实验

定时器是最常用的外设&#xff0c;常常需要使用定时器来完成精准的定时功能&#xff0c;I.MX6U 提供了多 种硬件定时器&#xff0c;有些定时器功能非常强大。本章我们从最基本的 EPIT 定时器开始&#xff0c;学习如何配置EPIT 定时器&#xff0c;使其按照给定的时间&#xff0c…

k8s部署学习

8s的架构 一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成&#xff0c;每个节点上都会安装不同的组件 1 master&#xff1a;集群的控制平面&#xff0c;负责集群的决策 ApiServer : 资源操作的唯一入口&#xff0c;接收用户输入的命令&#xff0c;提供认证、…

Java中对象的比较(equals、Comparable、Comparator)

文章目录 一、PriorityQueue中插入对象二、元素的比较 2.1、基本类型的比较2.2、对象比较的问题三、对象的比较 3.1、覆写基类的equals3.2、基于Comparable接口类的比较3.3、基于比较器比较3.4、三种方式对比 一、PriorityQueue中插入对象 前篇我们讲解了优先级队列&#xff0…

qt小练习

制作简易闹钟 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer> //定时器类 #include <QDebug> //信息调试类 #include <QMessageBox> //消息对话框类 #include <QTime> //时间类 #include…

大模型日报|4 篇必读的大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.清华、北航团队推出多智能体代码异常处理框架 Seeker 在现实世界的软件开发中&#xff0c;异常处理不当或缺失会严重影响代码的鲁棒性和可靠性。异常处理机制要求开发人员按照高标准来检测、捕获和管理异常&#x…

全网最详细k8s搭建部署

目录 Kubernetes的功能&#xff1a; Kubernetes的特点&#xff1a; 1. 安装要求 2. 部署内容 1、系统环境准备 2、所有禁用swap和本地解析 3、仓库配置&#xff0c;所有安装docker 4、所有节点设定docker的资源管理模式为systemd 5、所有阶段复制harbor仓库中的证书并…

python中计算分布的分位数及累积概率

本文讨论python中怎样计算分布的分位数及累积概率 ⭐️ 根据累计概率获取分位数 在 Python 中&#xff0c;你可以使用 scipy.stats 中的 ppf&#xff08;percent point function&#xff09;来根据累积概率获取分位数。ppf 是逆累积分布函数&#xff0c;也就是根据给定的累积…

前端笔记(一):父传子,子传父,获取DOM对象或组件,别名路径联想设置,elemntPlus

一、父传子 二、子传父 三、获取DOM对象或组件 把子组件的属性暴露给父组件 四、别名路径联想设置 1.jsconfig里只做联想配置&#xff1b; 2.vue.config.js里做实际转换&#xff0c;把转为src&#xff1b; 五、elemntPlus 1.按需导入 ①npm install element-plus --sav…

适合高新技术企业的内外网文件交换系统

在科技前沿的战场上&#xff0c;数据的快速和安全流通是企业维持竞争优势的关键。随着企业业务的全球化和科技的持续进步&#xff0c;内外网文件交换的需求不断增长&#xff0c;这同时也带来了一系列挑战。本文将讨论科技前沿领域在内外网文件交换中所面临的挑战&#xff0c;并…

【技术支持】家里智能电视不能联网重置小米路由器之路

问题现象 最近家里的路由器出现一点问题&#xff0c;现象是手机和电脑连接wifi后&#xff0c;都可以正常打开网页看视频。 但是小爱同学和小米盒子&#xff0c;都出现网络问题&#xff0c;不能正常播放音乐或者视频。 这是小米盒子的网络问题截图 这是和小米盒子连接的智能电…

AI时代大厂AI项目管理学习路线

AI时代避免被裁员&#xff0c;大厂AI项目管理学习路线主要包括&#xff1a; 1、AI项目管理基础技能。 2、项目管理AI技术知识。 3、数据分析与决策。 4、AI项目管理工具。 5、AI项目管理知识扩展。 01 AI项目管理基础技能。 AI项目管理基础技能构成了项目管理的骨架&…