数据结构-嵌入式入门
数据结构-嵌入式入门
什么是数据结构,即一种数据的结构,使用何种算法存储,方便数据计算
学习这种方法,可以提供一种编程的高级思维,简化内容实现
本文按 线性结构/非线性结构 分类,分别讲述了几种嵌入式常用的数据结构
(对于嵌入式而言,不需要很复杂的算法,普遍用包调参,更需要对常用结构进行熟练使用)
线性结构/非线性结构
1.线性结构(线性表)
线性:除去第一个和最后一个,每个元素有且仅有一个前驱和一个后驱
(前驱:当前元素的前一元素/后驱同理)
2.非线性结构
即有多个前驱/后驱
简单线性结构
顺序表
//数组,下标,一起分装在结构体内
//本质是一个数组
struct sequence_watch{
//数据域
int data[];
//指针域
int sub;//指向最后一个元素
//数据域在前,方便数据查看
//指针域在前,方便类型转换
//看个人喜好和技术手册
};
链表
//数值,指针,封装在结构体内
//首尾相连的结构体
常见链表:单链表,单向循环链表,双链表,双向循环链表,内核链表
struct list{
int data;
//最后一个链表指向头,则是循环链表
struct list *next;//指向下一个链表结构体
//struct list *prev;
};
内核链表:是linux内核的库函数的封装
是前辈给我们造好的工具,在使用链表时不用重复造轮子
//#include </usr/.../list.h>
//常用变量/函数/宏定义:
struct list_head;//使用内核链表的指针域
struct list_head{
struct list_head *next;
struct list_head *prev;
};
INIT_LIST_HEAD(&head->point);//初始化头链表
list_add(&node->point,&head->point);//头插
list_add_tail(&node->point,&head->point);//尾插
list_del(&node->point);//删除//记得释放内存
//在移至下一个链表前都可以使用(删除后可用)
//自行设置结构体的遍历//方便读取数据
list_for_each_entry(pos,&head->point,point){};//遍历//适合打印
list_for_each_entry_safe(pos,n,&head->point,point){};//安全遍历//适合操作//删除
list_for_each_entry_reverse(pos,&head->point,point){};//从后往前遍历
list_for_each_entry_reverse_safe(pos,n,&head->point,point);//安全从后往前遍历
//list_head 遍历//需要配合list_entry()才能读取//
//另一种读取方法:指针域放前,用强制类型转换为大结构体,再读取
list_for_each(pos,&head->point){}//遍历
list_for_each_safe(pos,n,&head->point){}//安全遍历
list_for_each_prev(pos,&head->point)//从后往前
list_for_each_prev_safe(pos,n,&head->point)//安全从后往前
//输出大结构体首地址//借寄生链表获取大结构体
list_entry(ptr,type,member);
//例:(struct corelist *)list_entry(pos,struct corelist,point)->data
内核链表原理好文<Linux内核链表——看这一篇文章就够了>
栈和队列
栈:先进后出//FILO(first input last output)
//顺序栈(表实现)//链式栈(链表实现)
栈头/栈尾 入栈/出栈(压栈/弹栈)
队列:先进先出FIFO
//顺序队列//链式队列
队尾/队首 入队/出队
非线性结构
树/二叉树
1. 相关定义/概念
树(整体)/子树/二叉树(度=2 or 节点<=2)/满二叉树/完全二叉树
节点(点/有几个节点-有多少树杈)/根节点/叶子节点(度=0)
度(最多树杈)/树的度/节点的度
树的深度(数的高度)/分支
二叉树
//严格区分左右
//左/右孩子(左/右子树)
满二叉树
除'最后一层'的叶子节点,其他节点都为2
//只有'最后一层'为叶子节点
数学规律:节点数n/分支数n-1/叶子节点n*2-1/sum=1+2+4+8...
完全二叉树(连续/叶子-倒一倒二层)
1.从上到下,从左到右,'连续'不间断(重点在连续/不能间隔/不能从右往左)
2.'叶子'节点,只能在最后一层 or 倒数第二层
满二叉树/完全二叉树区别:
看最后一二层,缺不缺/排除满二叉树,并确定是否是完全二叉树
1.满二叉树 ---> 完全二叉树
2.完全二叉树 -\-> 满二叉树
3.普通二叉树(非完全二叉树)
2. 二叉树的遍历
二叉树的四种遍历:(技巧:先补全再遍历)//注意 起始点 与 技巧
前序: 根左右(技巧:遇到即输出)
中序: 左根右(技巧:缺右直接输出)
后序: 左右根(技巧:只看最后一个)
层序: 上至下,左至右
二叉树代码
1.存储
直接节点传输
规则数组存储//左2n+1//右2n+2
2.遍历//v函数 p打印//嵌套递归使用
前序: v(p/v/v)
中序: v(v/p/v)
后序: v(v/v/p)
层序: 队列结构
入队(root)
while(队内不空){
出队
入队(出队->lchild)
入队(出队->rchild)
}
二叉树推导:(两序求一序)
技巧://计算->画图->求值
1.前序 第一个节点:根节点
2.中序 根节点/左边左子树/右边右子树
3.后序 最后一个节点:根节点
4.每一点都可以是根节点
->前中:借中找前一(先左后右)
->后中:借中找后一(先右后左) or 双倒前一倒
->前后:没法定左右,答案不唯一//必须有一个中序才能推
(简化:中间的划掉,已被使用的划掉)
图
1. 相关定义/概念
顶点:节点数
边:节点之间的连接
顶点度:节点有多少边连接(连接个数)
有向图/无向图:有无箭头表示方向(单连接/双连接)
有向图专属概念->入度/出度
(箭头指向节点/箭头指向别的节点)的个数
2. 图的存储
//关键点(1.data 2.flag 3.list)
邻接矩阵//数组存储
1.顶点表(顶点集)//一维数组存放顶点 A B C D
//顶点表影响边表->边表要对应顶点表
//存放顺序自行规定 or 按照要求
2.边表//二维数组存放顶点之间的关系//以顶点表为基准
A B C D
A//size=顶点表^2
B//连接为 1//不连接为 0
C//中轴为0(自己不能与自己连)//无向图对称(双向连接)
D//有向图(约定)->行为主方向
领接表//链表存储
1.用'结构体数组'存放'顶点信息'和'边链表头节点'
struct xxx{
int 顶点;
边链表头节点 *head;//不是指向结构体
//单向链表存储
}A,B,C,D;
2.存放所有顶点相邻信息
A->B->D->NULL;//有节点A,BD与A相接
B->A->C->D->NULL;
C->B->D->NULL;
D->A->B->D->NULL;
A<->B;A<->D;B<->C;B<->D;C<->D;//不是领接表//只是多个循环的链表
//链表指针 指向 结构体//领接表指针 指向 链表
3. 图的遍历//吃糖果->只吃一个/全部吃完
深度优先遍历
1.从指定顶点开始,一直往下遍历相邻的其他节点
2.直到无路可走,退回
//从什么开头遍历//按什么顺序遍历//相邻节点是什么
另一种说法:从头节点开始,找一个相邻节点(按顺序选择/找过的不找),直到全部遍历
广度优先遍历
1.指定节点开始,遍历所有相邻节点(遍历过的不遍历),再选择一个节点
2.按选择节点,遍历所有相邻节点,循环/直到全部遍历
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!