要求在 C 里手写数据结构、禁用 STL 容器的作业,考的核心不是算法本身,而是你能否正确管理节点内存。算法写对了但内存管乱了,一样拿不到分。

链表:指针重连的顺序
单链表删除节点时,顺序错了会丢失后继节点:
/* 错误:先断链再保存后继 */
prev->next = NULL; /* 后继节点地址丢了,内存泄漏 */
free(cur);
/* 正确:先保存,再重连,最后释放 */
Node *next = cur->next;
prev->next = next;
free(cur);
头节点删除还要额外处理「链表为空」和「删除的是头节点」两种边界。
二叉树:递归删除必须后序
void tree_free(Node *root) {
if (!root) return;
tree_free(root->left); /* 先释放子树 */
tree_free(root->right);
free(root); /* 最后释放自己 */
}
如果先 free(root),左右子树的地址就丢了——这是二叉树作业里最高频的泄漏来源。
哈希表:冲突链的归属
拉链法哈希表里,每个桶挂一条链表。常见错误是:
- 销毁哈希表时只释放了桶数组,没遍历释放每条冲突链。
- rehash 扩容时把旧节点复制而不是移动,导致两份内存。
- 删除键值对时只从链表摘除、没有 free 节点。
动态数组:realloc 的陷阱
/* 错误:realloc 失败会返回 NULL,原指针丢失 */
arr = realloc(arr, new_size * sizeof(int));
/* 正确:先用临时变量接 */
int *tmp = realloc(arr, new_size * sizeof(int));
if (!tmp) { /* 处理失败,arr 仍然有效 */ }
arr = tmp;
另外,realloc 可能返回新地址,所有指向原数组的指针都会失效。
图:邻接表的释放顺序
邻接表通常是「顶点数组 + 每个顶点的边链表」。释放时要先释放所有边链表,再释放顶点数组——顺序反了会丢失边链表的入口地址。
交付前的自查
- 空结构、单元素、删除头节点三种边界是否都测试过。
- Valgrind 是否报告所有堆块已释放。
- 是否存在「删除后继续访问」的路径。
- 所有分配函数的返回值是否都做了判空。
- 错误分支(如分配失败)是否也做了清理。
需要 C 语言数据结构代写 支持,可以联系我们,或了解 C 语言代码代写服务。
