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

嵌入式学习笔记DAY20(链表,gdb调试)

一、链表

1. 练习

  • 单链表——尾插
int InsertTailLinkList(LinkList *ll, DATATYPE *data)
{// 创建新节点并分配内存LinkNode* newnode1 = malloc(sizeof(LinkNode));// 内存分配失败检查if (newnode1 == NULL){fprintf(stderr, "InsertTailLinkList malloc failed\n");return 1;  // 返回错误码1表示内存分配失败}// 复制数据到新节点memcpy(&newnode1->data, data, sizeof(DATATYPE));newnode1->next = NULL;  // 新节点的next指针置为NULL,作为尾节点// 处理链表为空的特殊情况if(IsEmptyLinkList(ll)){ll->head = newnode1;  // 空链表时,新节点直接成为头节点}else{// 链表非空时,寻找当前尾节点LinkNode* tail = ll->head;// 循环遍历直到找到尾节点(next为NULL的节点)while(tail->next) {tail = tail->next;}// 将新节点插入到尾节点之后tail->next = newnode1;}ll->clen++;  // 更新链表长度return 0;    // 返回0表示插入成功
}
  • 链表——按位置插入 
int InsertAtPosition(LinkList *ll, int pos, DATATYPE *data) {if (ll == NULL || pos < 0 || pos > ll->clen) {return 1; // pos的位置应该在合理范围之内}if (pos == 0) {return InsertHeadLinkList(ll, data); //如果pos为0,那么直接掉迎头差}//创建新节点,为新节点分配内存,使用memcpy将data复制到新节点的data成员中LinkNode *newnode = malloc(sizeof(LinkNode));if (newnode == NULL) {fprintf(stderr, "InsertAtPosition malloc failed\n");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));//遍历到第pos-1个节点(即想要插入位置的前面一个节点)LinkNode *prev = ll->head; //for (int i = 0; i < pos - 1; i++) {prev = prev->next;}newnode->next = prev->next; //新节点的 next 指向 prev 的下一个节点prev->next = newnode;       // prev 的 next 指向新节点ll->clen++;return 0;
}
  • 修改链表
int ModifyLinkList(LinkList *ll, char *name, DATATYPE *data) 
{DATATYPE *tmp = FindLinkList(ll, name);if (NULL == tmp) {return 1;}memcpy(tmp, data, sizeof(DATATYPE));return 0;
}
  •  链表的销毁
int DestroyLinkList(LinkList *ll) 
{// 检查链表是否为空或已被销毁if (ll == NULL || ll->head == NULL) {return 0;  // 空链表无需处理,直接返回成功}LinkNode *tmp = ll->head;  // 初始化临时指针,指向链表头节点LinkNode *next;            // 用于保存下一个节点的指针// 遍历链表,逐个释放节点while (tmp != NULL) {next = tmp->next;  // 保存当前节点的下一个节点指针free(tmp);         // 释放当前节点的内存tmp = next;        // 移动临时指针到下一个节点}// 链表销毁后,重置链表头指针为NULL,节点计数为0ll->head = NULL;ll->clen = 0;return 0;  // 返回成功状态码
}

 

2.  gdb调试 

一般调试步骤与命令:

1、gcc -g  *.c 加上调试选项(eg:gcc -g main.c linklist.c)

2、gdb a.out(调试可执行文件,eg:gdb ./a.out)

3、r  运行(出现页面然后进行输入)

4、b fun.c:36 设置断点,运行到这个位置,程序自动暂停

  •  b :100          默认停在main.c的100行;
  •  b fun.c : 36     停在fun.c的36行
  •  b 函数名          eg: b InserPosLinkList)

5、n 执行下一步  步过(如果是函数,直接调用结束)

      s  步入自定义函数(系统函数不入)

6、使用p命令,查看变量或指针等数据

  •    p  变量: 显示变量值   eg:p len
  •    p  指针: 看地址          eg:p *data

7、q命令 退出(y)

3. 练习

  • 查找链表中间节点
DATATYPE *FindMiddleLinklist(LinkList *ll) {LinkNode *slow = ll->head;   //初始化慢指针slow,使其指向链表的头节点LinkNode *fast = ll->head;   //初始化快指针fast,使其也指向链表的头节点// 检查链表是否为空,如果为空,直接返回NULLif (NULL == ll) {return NULL;}// 使用快慢指针法寻找中间节点// 当快指针fast不为空,且fast的下一个节点和下下个节点都不为空时,循环继续while (fast != NULL && fast->next->next != NULL) {fast = fast->next->next;  // 快指针每次移动两步slow = slow->next;        // 慢指针每次移动一步}// 循环结束后,此时慢指针slow指向的节点即为中间节点(或中间偏右节点,取决于链表长度奇偶性)// 返回中间节点的数据指针return &slow->data;
}

如何返回偏前的中间节点?

修改循环条件,让快指针提前一步终止

 
LinkNode* FindMiddleLinklist(LinkList* ll) {if (ll == NULL || ll->head == NULL) return NULL;LinkNode* slow = ll->head;LinkNode* fast = ll->head;// 修改循环条件:fast->next->next != NULLwhile (fast != NULL && fast->next != NULL && fast->next->next != NULL) {slow = slow->next;fast = fast->next->next;}return slow;
}

  •  找倒数第k个节点
LinkNode* FindKthFromEnd(LinkList* ll, int k) 
{// 处理空链表以及无效的k值if (ll == NULL || ll->head == NULL || k <= 0) return NULL;// 检查k是否超过链表长度if (k > ll->clen){fprintf(stderr, "Error: k (%d) exceeds list length (%d)\n", k, ll->clen);return NULL;}LinkNode* fast = ll->head;LinkNode* slow = ll->head;// 1.快指针先走k步for (int i = 0; i < k; i++) {fast = fast->next;}// 2.快慢指针同步移动while (fast != NULL) {slow = slow->next;fast = fast->next;}return slow;  // 返回倒数第k个节点
}

算法核心思想

假设链表总长度为 n,倒数第 k 个节点的正向位置是 n-k+1(从 1 开始计数)。例如:

  • 链表 10 → 20 → 30 → 40 → 50(n=5)

  • 倒数第 2 个节点是 40,其正向位置是 5-2+1=4

双指针法的巧妙之处在于:

  1. 让快指针(fast)先走 k 步,此时快指针距离链表尾部还有 n-k 步。

  2. 然后让慢指针(slow)和快指针同步移动。

  3. 当快指针到达尾部(NULL)时,慢指针恰好走了 n-k 步,此时慢指针的位置就是 n-k+1(倒数第 k 个节点)。

  •  链表的逆序
int RevertLinkList(LinkList *ll) {LinkNode *prev = NULL;LinkNode *tmp = ll->head;LinkNode *next = tmp->next;int len = GetSizeLinkList(ll);if (len < 2) {return 1;}while (1) {tmp->next = prev;prev = tmp;tmp = next;if (NULL == tmp)break;next = next->next;}ll->head = prev;return 0;
}

    相关文章:

  • 前端~三维地图(cesium)动态材质飞线
  • 香橙派/树莓派读取GY39数据
  • QMK键盘编码器(Encoder)(理论部分)
  • 实战案例:采集 51job 企业招聘信息
  • 安卓system/文件夹下的哪些文件夹可以修改为别的设备的
  • SRM电子采购管理系统:Java+Vue,集成供应商管理,实现采购流程数字化与协同优化
  • 麒麟环境下Selenium的使用
  • 如何高效集成MySQL数据到金蝶云星空
  • Spring的 @Validate注解详细分析
  • 力扣-108.将有序数组转换为二叉搜索树
  • idea 启动Springboot项目在编译阶段报错:java: OutOfMemoryError: insufficient memory
  • VS Code 新旧版本 Remote-SSH 内网离线连接服务器方法(版本 ≤ 1.78.x 及 ≥ 1.79.0)
  • 实验五:以太网UDP全协议栈的实现(通过远程实验系统)
  • 代码随想录算法训练营Day58
  • CSP信奥赛新增的算法-马拉车算法(Manacher‘s Algorithm)
  • 初识java
  • git切换分支后需要pull吗
  • cGAS-STING通路
  • 解决 TypeError: unsupported operand type(s) for -: ‘NoneType‘ and ‘float‘ 错误
  • 前端服务器部署分类总结
  • 齐白石精品在波士顿展出,“白石画屋”呈现水墨挥洒
  • 思想史家陈谷嘉逝世,曾为岳麓书院当代复兴奠定重要基础
  • 美叙领导人25年来首次会面探索关系正常化,特朗普下令解除对叙经济制裁
  • 马上评|让查重回归促进学术规范的本意
  • 巴方:印度上周导弹袭击造成至少40名平民死亡
  • 梅花奖在上海丨陈丽俐“婺剧折戏专场”:文戏武做,武戏文唱