嵌入式数据结构笔记(二):内存工具与链表操作
1.Valgrind 简介
Valgrind 是 GNU 提供的开源内存调试工具,主要用于检测以下问题:
- 内存错误(如非法访问、越界读写)
- 内存泄漏(已分配但未释放的内存)
2.Valgrind 安装
网络配置
确保系统网络连接正常,以下为典型安装流程图示。

解除系统锁
安装的时候报错,需要sudo命令来删除锁,删除完再安装。
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/dpkg/lock
安装工具
sudo apt-get install valgrind
运行检测
通过以下命令检测程序内存问题:
valgrind ./a.out
2.链表核心操作
查找算法
- 中间节点:使用快慢指针法,快指针每次移动两步,慢指针每次移动一步。
- 倒数第k节点:双指针法,前指针先移动k步,后指针再同步移动。
//查找中间结点,不知道长度的情况下 Node_t *midnode(Link_t *plink) {if(plink->phead == NULL){return NULL;}Node_t *ptmp = plink->phead;int len = 0, i;while(ptmp){ptmp = ptmp->pnext;++len;}ptmp = plink->phead;for(i = 1;i <= len / 2 ;++i){ptmp = ptmp->pnext;}return ptmp; }//快慢指针法找中间结点(时间复杂度低) Node_t *fsmidnode(Link_t *plink) {if(plink->phead == NULL){return NULL;}Node_t *pfast = plink->phead;Node_t *pslow = plink->phead;while(NULL != pfast){pfast = pfast -> pnext;if(NULL == pfast){break;}pfast = pfast -> pnext;pslow = pslow -> pnext;}return pslow; }
//查找倒数第k个结点,不知道长度的情况下
Node_t *k(Link_t *plink, int k)
{if(plink->phead == NULL){return NULL;}Node_t *ptmp = plink->phead;int len = 0, i;while(ptmp){ptmp = ptmp->pnext;++len;}ptmp = plink->phead;for(i = 1;i <= len - k;++i){ptmp = ptmp->pnext;}return ptmp;
}//快慢指针找倒数第k个
Node_t *knode(Link_t *plink, int k)
{if(plink->phead == NULL){return NULL;}Node_t *pfast = plink->phead;Node_t *pslow = plink->phead;int i;for(i = 1;i <= k;++i){if(NULL == pfast){return NULL;}pfast = pfast -> pnext;}while(NULL != pfast){pslow = pslow -> pnext;pfast = pfast -> pnext;}return pslow;
}
3.结构调整
- 链表逆序:通过迭代或递归反转指针方向。
void reverslink(Link_t *plink) {if(plink->phead == NULL){return;}Node_t *pinsert = NULL;Node_t *ptmp = plink->phead;plink->phead = NULL;while (ptmp != NULL){pinsert = ptmp;ptmp = ptmp->pnext;pinsert->pnext = plink->phead;plink->phead = pinsert;} } - 链表排序
void insertSort(Link_t *plink) {if(plink->phead == NULL){return;}Node_t *pinsert = plink -> phead -> pnext;Node_t *ptmp = plink -> phead -> pnext;Node_t *p = plink -> phead;plink -> phead -> pnext = NULL;while(ptmp){ptmp = ptmp -> pnext;if(plink -> phead -> data >= pinsert -> data){pinsert -> pnext = plink -> phead;plink ->phead = pinsert;}else{p = plink -> phead;while(p -> pnext != NULL && (pinsert -> data) > (p -> pnext -> data)){p = p -> pnext;}pinsert -> pnext = p -> pnext;p -> pnext = pinsert;}pinsert = ptmp;} }
4.环链检测
- 有环链表判断:快慢指针相遇即存在环。
void ringlink(Link_t *plink) {if(plink->phead == NULL || plink -> phead -> pnext == NULL){return;}Node_t *ptmp = plink -> phead;while(ptmp -> pnext != NULL){ptmp = ptmp -> pnext;}ptmp -> pnext = plink -> phead; }int islinkring(Link_t *plink) {if(plink->phead == NULL || plink -> phead -> pnext == NULL){return 0;}Node_t *pfast = plink -> phead;Node_t *pslow = pfast;while(1){pfast = pfast -> pnext -> pnext -> pnext;pslow = pslow -> pnext;if(pfast == pslow && pfast != NULL && pslow != NULL){break;}}return 1; } - 约瑟夫问题:通过循环链表模拟 Elimination Game。
Node_t *last_node(Link_t *plink, int clen) {ringlink(plink);Node_t *ptmp = plink -> phead;Node_t *p = ptmp;Node_t *q;while(clen != 1){q = ptmp -> pnext;ptmp = ptmp -> pnext -> pnext;p = ptmp -> pnext;free(ptmp);ptmp = p;q -> pnext = ptmp;--clen; } return p; }
4.链表类型解析
| 循环链表 | 有环链表 |
|---|---|
| 首尾节点显式连接 | 任意节点形成环结构 |
