重头开始嵌入式第三十七天(数据结构 链表)

embedded/2024/9/26 1:24:06/

单向链表

单向链表是一种常见的数据结构

一、结构组成

- 节点:单向链表由多个节点组成。每个节点包含两个部分,一个是存储数据的部分,可以存储各种类型的数据,如整数、字符、结构体等;另一个是指向下一个节点的指针,用于连接链表中的各个节点。

- 头指针:链表有一个特殊的指针称为头指针,它指向链表的第一个节点。如果链表为空,头指针为 NULL。

二、特点

- 动态性:单向链表的长度可以在运行时动态改变,可以根据需要随时添加或删除节点。

- 内存分配:节点通常是在运行时动态分配内存,可以在堆上使用诸如 malloc (在 C 语言中)或 new (在 C++中)来分配内存空间。

- 遍历方式:只能从链表的头节点开始,沿着指向下一个节点的指针依次访问各个节点,直到到达链表的末尾(即下一个指针为 NULL)。

三、基本操做

- 插入节点:可以在链表的头部、尾部或中间位置插入新的节点。插入操作需要修改相应节点的指针,使其指向新插入的节点。

- 删除节点:根据特定条件删除链表中的节点。删除操作也需要调整相应节点的指针,以保持链表的连续性。

- 查找节点:可以遍历链表查找满足特定条件的节点。

单向链表在很多场景下都有广泛应用,比如实现栈、队列等数据结构,以及在各种算法和程序中进行动态数据存储和管理。

创建ADT

typedef struct person {char name[32];char sex;int age;int score;
}DATATYPE;typedef struct node {DATATYPE data;struct node *next;
}SLinkNode;typedef struct list {SLinkNode *head;int clen;
}SLinkList;

1.创建链表

SLinkList * CreateSLinkList()
{SLinkList* sll = (SLinkList*) malloc(sizeof(SLinkList));if(NULL == sll){perror("CreateSLinkList malloc");return NULL;}sll->head = NULL;sll->clen = 0 ;return sll;
}

2.头插数据

int InsertHeadSLinkList(SLinkList* sll,DATATYPE *data)
{SLinkNode* newnode = (SLinkNode*)malloc(sizeof(SLinkNode));if(NULL == sll){perror("inserthead malloc");return 1;}memcpy(&newnode->data ,data,sizeof(DATATYPE));newnode->next = NULL;if(IsEmptySLinkList(sll)){sll->head = newnode;}else{newnode->next = sll->head;sll->head = newnode;}sll->clen++;return 0;
}

3.删除数据

int DeleteSLinkList(SLinkList*sll,FUN fun,void* arg)
{//待删除节点的前一个指针SLinkNode*prev = NULL;SLinkNode*tmp = sll->head;int len = GetSizeSLinkList(sll);if(len == 1){free(sll->head);sll->head = NULL;sll->clen = 0 ;return 0;}//至少2个节点while(1){if(fun(&tmp->data,arg)){if(prev){prev->next = tmp->next;}else{sll->head = tmp->next;}free(tmp);sll->clen--;return 0;}prev = tmp;tmp = tmp->next;if(NULL == tmp){//删除失败//return 1;break;}}return 1;
}

4.更改数据

int ModifySlinkList(SLinkList*sll,FUN fun,void* arg,DATATYPE*newdata)
{SLinkNode* tmp= FindSlinkList(sll,fun, arg);if(NULL == tmp){fprintf(stderr,"can find\n");return 1;}else{memcpy(&tmp->data,newdata,sizeof(DATATYPE));}return 0;
}

5.清空链表

int DestroySLinkList(SLinkList *sll) {SLinkNode *tmp = sll->head;while (1) {tmp = sll->head;if (!tmp)break;sll->head = sll->head->next;free(tmp);}free(sll);return 0;
}

6.查找数据

SLinkNode * FindSlinkList(SLinkList*sll,FUN fun,void* arg)
{SLinkNode* tmp = sll->head;int len = GetSizeSLinkList(sll);int i =  0;for(i=0;i<len;i++){//if(0==strcmp(tmp->data.name,name))if(fun(&tmp->data,arg)){return tmp;}tmp = tmp->next;}return NULL;
}

7.尾插数据

int InserTailSlinkList(SLinkList* sll,DATATYPE *data)
{SLinkNode* newnode = (SLinkNode*)malloc(sizeof(SLinkNode));SLinkNode* tmp=sll->head;if(NULL == sll){perror("inserthead malloc");return 1;}memcpy(&newnode->data ,data,sizeof(DATATYPE));newnode->next = NULL;if(IsEmptySLinkList(sll)){sll->head = newnode;}else{while(tmp->next)tmp=tmp->next;tmp->next=newnode;}sll->clen++;return 0;
}

8.按位插入

int InserPosSlinkList(SLinkList* sll,DATATYPE *data,int pos){int len = GetSizeSLinkList(sll);if(pos<0 || pos > len){return 1;}if(0 == pos){return InsertHeadSLinkList(sll,data);}else if(pos == len){return InserTailSlinkList(sll,data);} else // mid{int i = 0;SLinkNode *prev = sll->head;for (i = 0; i < pos - 1; i++) {prev = prev->next;}SLinkNode *newnode = malloc(sizeof(SLinkNode));if (NULL == newnode) {perror("insert pos malloc");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = NULL;newnode->next = prev->next;prev->next = newnode;}sll->clen++;return 0;}

9.打印数据

int ShowSLinkList(SLinkList*sll)
{SLinkNode* tmp = sll->head ;while(tmp){printf("name:%s score:%d\n",tmp->data.name ,tmp->data.score);tmp= tmp->next ;//i++}return 0;
}


http://www.ppmy.cn/embedded/110002.html

相关文章

数据库超时排查

背景&#xff1a; 项目是用的springboot&#xff0c;连接池用的是hikaricp&#xff0c;且数据库连接做了LB配置&#xff0c;之前就是经常会有数据库出现问题&#xff0c;专家给到的解决方案。 数据连接io超时报错&#xff0c;排查了当时数据库各项指标都无显示异常&#xff0c;…

Docker Compose version v2.29.2 提示 exited with code 0 解决方案

问题描述&#xff1a; 使用 docker-compose up 启动容器时&#xff0c;老是报错exited with code 0&#xff0c;容器要么处于退出&#xff0c;要么处于重启阶段&#xff0c;查明原因后&#xff0c;是因为docker容器执行任务完成后就会处于exited状态&#xff0c;必须强制状态。…

分页插件jqGrid与Spring Boot项目整合

一、jqGrid分页插件使用 jqGrid是一个用来显示网格数据的jQuery插件。开发人员通过使用jqGrid可以轻松实现前端页面与后台数据的Ajax异步通信并实现分页功能&#xff0c;其特点如下&#xff1b; &#xff08;1&#xff09;兼容目前流行的Web浏览器 &#xff08;2&#xff09…

常见的设计模式

设计模式是面向对象设计中解决常见问题的一套最佳实践&#xff0c;它们为开发者提供了通用的解决方案。 1.单例模式&#xff08;Singleton Pattern&#xff09; 定义&#xff1a; 确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 应用场景&#xff1a; 需要控制实…

Java 访问修饰符详解:public、private、protected 及默认访问权限

在Java编程中&#xff0c;访问修饰符&#xff08;Access Modifiers&#xff09;是控制类、方法、字段和构造函数访问范围的重要机制。Java提供了四种主要的访问修饰符&#xff1a;public、private、protected和默认&#xff08;不写修饰符&#xff09;。不同的修饰符决定了成员…

TwinCAT3 实时核中ADS实现C++ server、clinet数据传输

一、基本概念 ADS &#xff1a;Automation Device Specification&#xff0c;ADS设备间进行通信的协议规范。协议定义了ADS device之间如何寻址对方、ADS device之间可以执行哪些操作、执行这些操作需要哪些参数&#xff0c;以及操作完成后如何返回结果等。从编程角度看&#…

【JavaSE】Java基本数据类型缓存池

new Integer(18) 、 Integer.valueOf(18) 、Integer.valueOf(300) 的区别 new Integer(18) &#xff1a;每次都会创建一个新对象Integer.valueOf(x)&#xff1a; x in [-128, 127]&#xff1a;使用缓存池中的对象x not in [-128, 127]&#xff1a;创建新对象 Integer缓存池大…

【深度学习】【OnnxRuntime】【C++】模型转化、环境搭建以及模型部署的详细教程

【深度学习】【OnnxRuntime】【C】模型转化、环境搭建以及模型部署的详细教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【OnnxRuntime】【C】模型转化、环境搭建以及模型部署的详细教程前言模型转换--pytorch转onnxWindows平…