单链表操作实现
1.什么是单链表?
单链表是一种常见的线性数据结构,由一系列节点组成,每个节点包含两个部分:数据域 和 指针域。数据域存储实际数据,指针域指向下一个节点。在单链表中,数据元素可以非连续地存储在内存中,而节点之间通过指针相互连接。
2.代码实现
链表的创建、插入、删除、查找等常用操作。
其他辅助函数
1.删除最小值结点
- bool LList_MinDel(LList_t *Head)
- {
- // 判断链表是否为空:如果头节点的 next 为 NULL,说明链表没有有效节点
- if (NULL == Head->next)
- {
- printf("链表空!\n");
- return false;
- }
- // 定义当前遍历节点 current,从第一个有效节点开始
- LList_t *current = Head->next;
- LList_t *pre_current = Head;
- // 定义最小值节点 MinNode,初始为第一个有效节点
- LList_t *MinNode = current;
- LList_t *pre_MinNode = Head;
- // 遍历链表,寻找最小值节点
- while (current != NULL)
- {
- // 如果当前节点的 data 小于最小值节点的 data
- if(current->data < MinNode->data)
- {
- // 更新最小值节点及其前驱节点
- MinNode = current;
- pre_MinNode = pre_current;
- }
- // 继续向后遍历
- pre_current = current;
- current = current->next;
- }
- // 找到最小值节点后,将其从链表中删除
- pre_MinNode->next = MinNode->next;
- free(MinNode);
- return true;
- }
复制代码 2.查找倒数第 k 个节点(快慢指针法)
- int findKthFromEnd(LList_t *Head, int k)
- {
- if (Head == NULL || k <= 0) {
- printf("无效输入:k必须为正整数且链表不能为空\n");
- return 0;
- }
- LList_t *fast = Head;
- LList_t *slow = Head;
- int steps = 0;
- // fast 先走 k 步
- while (steps < k) {
- if (fast == NULL) {
- printf("链表长度不足 %d 个节点,无法查找倒数第 %d 个节点\n", k, k);
- return 0;
- }
- fast = fast->next;
- steps++;
- }
- // 如果 fast 已经为 NULL,说明链表正好有 k 个节点
- if (fast == NULL) {
- printf("倒数第 %d 个结点的 data 值为: %d\n", k, slow->data);
- return 1;
- }
- // 同时移动 fast 和 slow
- while (fast != NULL) {
- fast = fast->next;
- slow = slow->next;
- }
- // 此时 slow 指向倒数第 k 个节点
- printf("倒数第 %d 个结点的 data 值为: %d\n", k, slow->data);
- return 1;
- }
复制代码快慢指针经典算法。fast 先走 k 步,然后 slow 和 fast 一起走,当 fast 到达末尾时,slow 正好在倒数第 k 个位置。
3.主函数测试
- int main(int argc, char const *argv[])
- {
- // 创建链表
- printf("=== 创建空链表 ===\n");
- LList_t *head = LList_Create();
- if (head != NULL) {
- printf("链表创建成功!\n");
- }
- LList_Print(head);
-
- // 测试头插法
- printf("\n=== 测试头插法 ===\n");
- LList_HeadInsert(head, 10);
- LList_HeadInsert(head, 20);
- LList_HeadInsert(head, 30);
- LList_Print(head); // 预期结果: 30 20 10
-
- // 测试尾插法
- printf("\n=== 测试尾插法 ===\n");
- LList_TailInsert(head, 40);
- LList_TailInsert(head, 50);
- LList_Print(head); // 预期结果: 30 20 10 40 50
-
- // 测试指定位置插入
- printf("\n=== 测试指定位置插入 ===\n");
- LList_DestInsert(head, 20, 25); // 在20后插入25
- LList_Print(head); // 预期结果: 30 20 25 10 40 50
- LList_DestInsert(head, 100, 99); // 尝试插入到不存在的节点后
-
- // 测试查找倒数第k个节点
- printf("\n=== 测试查找倒数第k个节点 ===\n");
- findKthFromEnd(head, 1); // 预期结果: 50
- findKthFromEnd(head, 3); // 预期结果: 10
- findKthFromEnd(head, 10); // 预期结果: 链表长度不足
-
- // 测试删除头节点
- printf("\n=== 测试删除头节点 ===\n");
- LList_HeadDel(head);
- LList_Print(head); // 预期结果: 20 25 10 40 50
-
- // 测试删除尾节点
- printf("\n=== 测试删除尾节点 ===\n");
- LList_TailDel(head);
- LList_Print(head); // 预期结果: 20 25 10 40
-
- // 测试删除指定节点
- printf("\n=== 测试删除指定节点 ===\n");
- LList_DestDel(head, 25);
- LList_Print(head); // 预期结果: 20 10 40
- LList_DestDel(head, 100); // 尝试删除不存在的节点
-
- // 添加几个节点用于测试删除最小值
- printf("\n=== 测试删除最小值节点 ===\n");
- LList_TailInsert(head, 5);
- LList_HeadInsert(head, 35);
- LList_TailInsert(head, 15);
- LList_Print(head); // 预期结果: 35 20 10 40 5 15
- LList_MinDel(head); // 删除最小值5
- LList_Print(head); // 预期结果: 35 20 10 40 15
- LList_MinDel(head); // 删除最小值10
- LList_Print(head); // 预期结果: 35 20 40 15
-
- // 释放链表内存
- printf("\n=== 释放链表内存 ===\n");
- while (head->next != NULL) {
- LList_HeadDel(head);
- }
- free(head);
- head = NULL;
- printf("链表已释放\n");
-
- return 0;
- }
复制代码 测试结果:
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |