C语言链表元素迁移问题:将左侧链表首元素移至右侧链表末尾
C语言实现左侧链表首元素移至右侧链表末尾功能
没问题,我来帮你搞定这个需求!咱们从基础的结构体定义开始,一步步实现核心功能,还会附上完整的测试代码方便你验证。
1. 定义链表节点结构体
首先咱们先把存储数据的结构体定义好,这里假设你要存的是int类型数据——如果是其他类型(比如字符串、自定义结构体),直接把data的类型替换掉就行:
// 链表节点结构体,存储数据和后继指针 typedef struct Node { int data; // 替换成你实际需要存储的数据类型 struct Node* next; } Node;
2. 核心移动函数实现
接下来是关键的移动逻辑:把左侧链表的第一个节点移到右侧链表的末尾。这里要注意几种边界情况,比如左侧链表为空、右侧链表为空的处理,还要避免野指针问题:
// 将左侧链表的首个元素移至右侧链表末尾 // 参数用二级指针是因为要修改外部的链表头指针 void moveFirstToRight(Node** leftHead, Node** rightHead) { // 左侧链表为空的话直接返回,啥也干不了 if (*leftHead == NULL) { printf("左侧链表为空,无法执行移动操作!\n"); return; } // 步骤1:取出左侧链表的首节点 Node* movedNode = *leftHead; // 步骤2:更新左侧链表的头指针,指向原首节点的下一个节点 *leftHead = (*leftHead)->next; // 步骤3:把取出的节点挂到右侧链表的末尾 if (*rightHead == NULL) { // 如果右侧链表是空的,直接把这个节点作为右侧的新头 *rightHead = movedNode; movedNode->next = NULL; // 必须置空,防止野指针 } else { // 遍历右侧链表找到最后一个节点 Node* temp = *rightHead; while (temp->next != NULL) { temp = temp->next; } // 将新节点挂到最后一个节点的后继位置 temp->next = movedNode; movedNode->next = NULL; } }
3. 完整测试代码
下面是一个可以直接编译运行的完整示例,包含链表创建、打印、移动和内存释放的逻辑,你可以直接跑起来看效果:
#include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node; // 创建一个新的链表节点 Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; return newNode; } // 打印链表内容,方便查看状态 void printList(Node* head, const char* listName) { printf("%s链表:", listName); Node* temp = head; while (temp != NULL) { printf("%d ", temp->data); temp = temp->next; } printf("\n"); } // 移动函数(和上面的一样) void moveFirstToRight(Node** leftHead, Node** rightHead) { if (*leftHead == NULL) { printf("左侧链表为空,无法执行移动操作!\n"); return; } Node* movedNode = *leftHead; *leftHead = (*leftHead)->next; if (*rightHead == NULL) { *rightHead = movedNode; movedNode->next = NULL; } else { Node* temp = *rightHead; while (temp->next != NULL) { temp = temp->next; } temp->next = movedNode; movedNode->next = NULL; } } int main() { // 构建初始左侧链表:1 -> 2 -> 3 Node* leftHead = createNode(1); leftHead->next = createNode(2); leftHead->next->next = createNode(3); // 右侧链表初始为空 Node* rightHead = NULL; printf("=== 初始状态 ===\n"); printList(leftHead, "左侧"); printList(rightHead, "右侧"); // 第一次移动 moveFirstToRight(&leftHead, &rightHead); printf("\n=== 第一次移动后 ===\n"); printList(leftHead, "左侧"); printList(rightHead, "右侧"); // 第二次移动 moveFirstToRight(&leftHead, &rightHead); printf("\n=== 第二次移动后 ===\n"); printList(leftHead, "左侧"); printList(rightHead, "右侧"); // 第三次移动 moveFirstToRight(&leftHead, &rightHead); printf("\n=== 第三次移动后 ===\n"); printList(leftHead, "左侧"); printList(rightHead, "右侧"); // 尝试移动空的左侧链表 moveFirstToRight(&leftHead, &rightHead); // 记得释放内存,避免内存泄漏 Node* temp; while (rightHead != NULL) { temp = rightHead; rightHead = rightHead->next; free(temp); } return 0; }
4. 关键注意点
- 数据类型适配:如果你的结构体存储的不是int,只需要修改
data的类型,其他逻辑完全通用。 - 野指针防范:移动节点后一定要把
movedNode->next置为NULL,否则可能导致右侧链表出现循环或者非法内存访问。 - 内存管理:实际项目中别忘了释放链表节点的内存,避免内存泄漏。
- 指针参数:函数用二级指针是因为要修改外部的链表头指针——如果只用一级指针,函数内部的修改不会影响到外部的指针变量。
内容的提问来源于stack exchange,提问作者Ania
相关产品推荐
相关产品推荐

