在C语言中实现链表的逆序,使用哨兵头节点是一种常见的做法。哨兵头节点可以简化代码逻辑,特别是当链表为空时,可以避免空指针异常。下面是一个使用哨兵头节点逆序单链表的C语言实现
示例:
cpp
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建新节点
ListNode* createNode(int value) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (!newNode) {
exit(-1); // 分配内存失败,退出程序
}
newNode->val = value;
newNode->next = NULL;
return newNode;
}
// 逆序链表,使用哨兵头节点
void reverseList(ListNode** headRef) {
ListNode* prev = NULL;
ListNode* current = *headRef;
ListNode* next = NULL;
while (current != NULL) {
next = current->next; // 保存下一个节点
current->next = prev; // 当前节点指向前一个节点,实现逆序
prev = current; // 前一个节点移动到当前节点
current = next; // 当前节点移动到下一个节点
}
*headRef = prev; // 更新头节点
}
// 打印链表
void printList(ListNode* head) {
ListNode* temp = head;
while (temp != NULL) {
printf("%d ", temp->val);
temp = temp->next;
}
printf("\n");
}
// 主函数,测试逆序链表功能
int main() {
ListNode* head = createNode(1);
head->next = createNode(2);
head->next->next = createNode(3);
head->next->next->next = createNode(4);
printf("原始链表:");
printList(head);
reverseList(&head);
printf("逆序后链表:");
printList(head);
// 释放链表内存
ListNode* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
return 0;
}
在这个代码中,我们首先定义了链表节点的结构体ListNode
,然后提供了创建新节点的函数createNode
。reverseList
函数用来逆序链表,它使用了一个哨兵头节点,即第一个节点作为prev指针的初始位置,最后将头节点更新为prev指针所指向的节点。printList
函数用来打印链表的节点值。
在main
函数中,我们创建了一个简单的链表,并调用reverseList
函数进行逆序,然后打印出逆序后的结果。最后,我们释放了链表占用的内存。
请注意,在实际的项目开发中,还需要对代码进行适当的错误处理和边界条件检查,以确保程序的健壮性。
在C语言中,使用哨兵位头节点(dummy head)来逆序链表是一种常见的技巧,因为它可以简化边界条件的处理。以下是一个使用哨兵位头节点逆序单链表的示例代码:
// 链表节点的结构体定义
cpp
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建一个新的链表节点
cpp
ListNode* createNode(int value) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (!newNode) {
exit(-1); // 分配内存失败,退出程序
}
newNode->val = value;
newNode->next = NULL;
return newNode;
}
// 在链表的末尾添加一个新节点
cpp
void appendNode(ListNode** headRef, int value) {
ListNode* newNode = createNode(value);
ListNode* temp = *headRef;
if (temp == NULL) {
*headRef = newNode;
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
// 逆序链表,使用哨兵位头节点
cpp
void reverseList(ListNode** headRef) {
ListNode* prev = NULL;
ListNode* current = *headRef;
ListNode* next = NULL;
while (current != NULL) {
next = current->next; // 保存下一个节点
current->next = prev; // 当前节点指向前一个节点
prev = current; // 前一个节点移动到当前节点
current = next; // 当前节点移动到下一个节点
}
*headRef = prev; // 更新头节点
}
// 打印链表
cpp
void printList(ListNode* head) {
ListNode* temp = head;
while (temp != NULL) {
printf("%d ", temp->val);
temp = temp->next;
}
printf("\n");
}
// 主函数,测试逆序链表功能
cpp
int main() {
ListNode* head = NULL; // 哨兵位头节点
// 向链表中添加元素
appendNode(&head, 1);
appendNode(&head, 2);
appendNode(&head, 3);
appendNode(&head, 4);
printf("原始链表:");
printList(head);
// 逆序链表
reverseList(&head);
printf("逆序后链表:");
printList(head);
// 释放链表内存
ListNode* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
return 0;
}
总代码
#include <stdio.h>
#include <stdlib.h>
// 链表节点的结构体定义
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建一个新的链表节点
ListNode* createNode(int value) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (!newNode) {
exit(-1); // 分配内存失败,退出程序
}
newNode->val = value;
newNode->next = NULL;
return newNode;
}
// 在链表的末尾添加一个新节点
void appendNode(ListNode** headRef, int value) {
ListNode* newNode = createNode(value);
ListNode* temp = *headRef;
if (temp == NULL) {
*headRef = newNode;
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
// 逆序链表,使用哨兵位头节点
void reverseList(ListNode** headRef) {
ListNode* prev = NULL;
ListNode* current = *headRef;
ListNode* next = NULL;
while (current != NULL) {
next = current->next; // 保存下一个节点
current->next = prev; // 当前节点指向前一个节点
prev = current; // 前一个节点移动到当前节点
current = next; // 当前节点移动到下一个节点
}
*headRef = prev; // 更新头节点
}
// 打印链表
void printList(ListNode* head) {
ListNode* temp = head;
while (temp != NULL) {
printf("%d ", temp->val);
temp = temp->next;
}
printf("\n");
}
// 主函数,测试逆序链表功能
int main() {
ListNode* head = NULL; // 哨兵位头节点
// 向链表中添加元素
appendNode(&head, 1);
appendNode(&head, 2);
appendNode(&head, 3);
appendNode(&head, 4);
printf("原始链表:");
printList(head);
// 逆序链表
reverseList(&head);
printf("逆序后链表:");
printList(head);
// 释放链表内存
ListNode* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
return 0;
}
在这个代码中,我们首先定义了链表节点的结构体ListNode
。然后,我们提供了创建新节点和向链表末尾添加新节点的函数createNode
和appendNode
。reverseList
函数用来逆序链表,它使用了一个哨兵头节点prev
,并最终将头节点更新为prev
指针所指向的节点。printList
函数用来打印链表的节点值。
在main
函数中,我们创建了一个链表,并调用reverseList
函数进行逆序,然后打印出逆序后的结果。最后,我们释放了链表占用的内存。
请注意,在实际的项目开发中,还需要对代码进行适当的错误处理和边界条件检查,以确保程序的健壮性。