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

《嵌入式数据结构笔记(三):数据结构基础与双向链表》

1.Makefile代码管理精要

基本语法规则
目标-依赖关系:

目标文件: 依赖文件  编译命令  

自定义变量与指令

功能语法用途
变量定义OBJ = a.out简化重复路径
变量引用$(OBJ)替代目标文件名
头文件指定-I include_path自定义头文件路径
库文件指定-L lib_path自定义库文件路径
清理操作make clean删除目标文件

时间戳机制

  • 增量编译:仅重编译修改过的文件
  • 效率提升:避免全量编译

示例:

2.GCC编译四步流程

阶段指令输入输出核心任务
预处理gcc -E main.c -o main.i.c.i展开宏/头文件
编译gcc -S main.i -o main.s.i.s生成汇编代码
汇编gcc -c main.s -o main.o.s.o生成机器码
链接gcc main.o -o app.o可执行文件合并库与目标文件

3.双向链表核心操作

操作全流程

  1. 创建链表:初始化头尾指针
  2. 插入数据:头插法(高效)、尾插法(保序)
  3. 删除数据:头删、尾删、指定节点删除
  4. 数据操作:查找、修改、遍历
  5. 销毁链表:递归释放节点内存
    //头文件#ifndef  DOULINK_H
    #define  DOULINK_H//创建data数据
    typedef struct stu
    {int id;char name[32];int score;
    }Data_type_t;//创建结点对象
    typedef struct dounode
    {Data_type_t data;struct dounode *ppre;struct dounode *pnext;
    }DNode_t;//创建双向链表对象
    typedef struct doulink
    {DNode_t *phead;int clen;
    }DLink_t;//函数声明
    extern DLink_t *create_doulink();
    extern int insert_doulink_head(DLink_t *pdlink, Data_type_t data);
    extern int is_empty_doulink(DLink_t *pdlink);
    extern void DLink_for_each(DLink_t *pdlink, int dir);
    extern void insert_doulink_tail(DLink_t *pdlink, Data_type_t data);
    extern int delete_doulink_head(DLink_t *pdlink);
    extern int delete_doulink_tail(DLink_t *pdlink);
    extern void destory(DLink_t *pdlink);
    extern DNode_t *pnode(DLink_t *pdlink, char *name);
    extern DNode_t *modify(DLink_t *pdlink, char *name, int score);
    extern void delete_assign(DLink_t *pdlink, char *name);#endif
    
    #include "doulink.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>//创建双向链表
    DLink_t *create_doulink()
    {DLink_t *pdlink = malloc(sizeof(DLink_t));if(NULL == pdlink){printf("malloc error\n");}pdlink -> phead = NULL;pdlink -> clen = 0;return pdlink;
    }//判断链表是否为空
    int is_empty_doulink(DLink_t *pdlink)
    {return NULL == pdlink -> phead;
    }//头插
    int insert_doulink_head(DLink_t *pdlink, Data_type_t data)
    {DNode_t *pnode = malloc(sizeof(DNode_t));if(NULL == pnode){printf("malloc errror\n");}pnode -> data = data;pnode -> ppre = NULL;pnode -> pnext = NULL;if(is_empty_doulink(pdlink)){pdlink -> phead = pnode;}else{pnode -> pnext = pdlink -> phead;pdlink -> phead -> ppre = pnode;pdlink -> phead = pnode;}pdlink -> clen++;return 0;
    }//遍历
    void DLink_for_each(DLink_t *pdlink, int dir)
    {if(is_empty_doulink(pdlink)){return;}DNode_t *ptmp = pdlink -> phead;if(1 == dir){while(ptmp){printf("%d,%s,%d\n", ptmp -> data.id, ptmp -> data.name, ptmp -> data.score);ptmp = ptmp -> pnext;}}else{while(ptmp->pnext){ptmp = ptmp -> pnext;}while(ptmp){printf("%d,%s,%d\n", ptmp -> data.id, ptmp -> data.name, ptmp -> data.score);ptmp = ptmp -> ppre;}}
    }//尾插
    void insert_doulink_tail(DLink_t *pdlink, Data_type_t data)
    {if(is_empty_doulink(pdlink)){insert_doulink_head(pdlink, data);return;}else{DNode_t *pnode = malloc(sizeof(DNode_t));if(NULL == pnode){printf("malloc errror\n");}pnode -> data = data;pnode -> ppre = NULL;pnode -> pnext = NULL;DNode_t *ptmp = pdlink -> phead;while(ptmp -> pnext){ptmp = ptmp -> pnext; }ptmp -> pnext = pnode;pnode -> pnext = NULL;pnode -> ppre = ptmp;pdlink -> clen++;}
    }//头删
    int delete_doulink_head(DLink_t *pdlink)
    {if(is_empty_doulink(pdlink)){printf("error\n");return -1;}DNode_t *pdel = pdlink->phead;pdlink->phead = pdel->pnext;if(pdlink->phead != NULL){pdlink->phead->ppre = NULL;}free(pdel);pdlink->clen--;return 0;
    }//尾删
    int delete_doulink_tail(DLink_t *pdlink)
    {if(is_empty_doulink(pdlink)){printf("error\n");return -1;}DNode_t *ptmp = pdlink->phead;if (1 == pdlink->clen){free(ptmp);pdlink->phead = NULL;}else{while (ptmp->pnext != NULL){ptmp = ptmp->pnext;}ptmp->ppre->pnext = NULL;free(ptmp);pdlink->clen--;}return 0;
    }//摧毁链表
    void destory(DLink_t *pdlink)
    {DNode_t *ptmp = pdlink -> phead;while(ptmp){pdlink->phead = ptmp->pnext;free(ptmp);ptmp = pdlink->phead;}free(pdlink);
    }//根据名字找结点
    DNode_t *pnode(DLink_t *pdlink, char *name)
    {DNode_t *ptmp = pdlink -> phead;while(NULL != ptmp && strcmp(ptmp ->data.name , name) != 0){ptmp = ptmp -> pnext;}return ptmp;
    }//根据名字修改成绩
    DNode_t *modify(DLink_t *pdlink, char *name, int score)
    {DNode_t *ptmp = pnode(pdlink, name);ptmp -> data.score = score;return ptmp;
    }//根据名字删除结点
    void delete_assign(DLink_t *pdlink, char *name)
    {DNode_t *ptmp = pnode(pdlink, name);ptmp -> pnext -> ppre = ptmp -> ppre -> pnext;free(ptmp);pdlink -> clen--;
    }
    //主函数#include <stdio.h>
    #include "doulink.h"int main(void)
    {
    //创建双向链表Data_type_t stus[5] = {{1, "zhangsan", 99},{2, "lisi", 100}, {3, "wangwu", 90}, {4, "maliu", 56}, {5, "tianqi", 66}};DLink_t *pdlink = create_doulink();if (NULL == pdlink){return -1;}
    //头插insert_doulink_head(pdlink, stus[0]);insert_doulink_head(pdlink, stus[1]);insert_doulink_head(pdlink, stus[2]);insert_doulink_head(pdlink, stus[3]);insert_doulink_head(pdlink, stus[4]);//遍历DLink_for_each(pdlink, 1);printf("\n");DLink_for_each(pdlink, 9);
    //尾插insert_doulink_tail(pdlink, stus[3]);DLink_for_each(pdlink, 1);printf("\n");DLink_for_each(pdlink, 9);//头删    DLink_for_each(pdlink,1);printf("\n");delete_doulink_head(pdlink);DLink_for_each(pdlink,1);//尾删DLink_for_each(pdlink,1);printf("\n");delete_doulink_tail(pdlink);DLink_for_each(pdlink,1);//摧毁链表destory(pdlink);//根据名字找结点DNode_t *ret = pnode(pdlink, "lisi");printf("%s\n", ret -> data.name);printf("%p\n", ret);//根据名字改成绩DNode_t *ret = modify(pdlink, "maliu", 0);printf("%d,%s,%d\n", ret -> data.id, ret -> data.name, ret -> data.score);
    //根据名字删结点    delete_assign(pdlink,"lisi");return 0;
    }
    //makefileOBJ=a.out
    SRC=main.c
    SRC+=doulink.c
    INC=./
    CC=gcc$(OBJ):$(SRC)$(CC) $^ -o $@ -I$(INC)clean:rm $(OBJ)

数据结构特点

特性优势局限
双向指针支持正反向遍历(O(1)访问相邻节点)额外8字节内存开销
动态内存按需分配无限制内存碎片风险
非连续存储避免数据搬移CPU缓存命中率降低

4.关键技巧总结

Makefile高效实践

  • 使用%.o: %.c通配符简化多文件编译
  • 通过-I/-L分离路径
  • clean规则需包含rm -f *.o app

5.总结

Makefile核心价值

  • 自动化编译与依赖管理
  • 时间戳实现增量编译

GCC四层转换本质
源码 → 汇编 → 机器码 → 可执行文件

双向链表优势

  • O(1)头尾操作
  • 双向遍历灵活性

双向链表的结构

http://www.dtcms.com/a/316868.html

相关文章:

  • 应急响应排查思路
  • MLIR Bufferization
  • JWT 签名验证失败:Java 与 PHP 互操作问题解决方案
  • OpenHarmony 5.0 Settings中wifi删除密码立刻去输入密码连接,连接不上
  • 性能测试终极指南:从指标到实战
  • 自动驾驶中的传感器技术24——Camera(15)
  • Mybatis的应用及部分特性
  • 机器学习——集成学习(Ensemble Learning):随机森林(Random Forest),AdaBoost、Gradient Boosting,Stacking
  • 企业级Redis Cluster部署详解及演练
  • 森赛睿科技成为机器视觉产业联盟会员单位
  • 解决cv::dilate处理后的图像边缘像素出现异常值的问题
  • 结构化设计工具与技术详解
  • Spring 的优势
  • 内部排序算法总结(考研向)
  • 从递归到动态规划-解码方法Ⅱ
  • 软件测试面试如何避坑呢?
  • 8.5 各种攻击实验
  • 使用 BAML 模糊解析改进 LangChain 知识图谱提取:成功率从25%提升到99%
  • 无人机陀螺仪模块技术解析
  • SQL的LEFT JOIN优化
  • 【C语言】动态内存管理详解
  • Centos7 、9 、OpenEuler 22、24对比
  • TCP协议与UDP协议
  • 十六、请求响应-响应:三层架构-分层解耦
  • 信息安全的概述
  • RabbitMQ延时队列的两种实现方式
  • C++算法竞赛篇(九)字符数组题型讲解
  • 坚鹏:AI智能体软件是知行学成为AI智能体创新应用引领者的抓手
  • uvm-register-backdoor-access
  • SpringBoot AI心理学训练实战