#include <stdio.h>
#include <stdlib.h>
// 定义链表节点
typedef struct ListNode {
int value; // 节点存储的数据
struct ListNode* next; // 指向下一个节点的指针
} ListNode;
//通常,链表通过一个指向其第一个节点的指针来表示。
// 创建空链表
ListNode* List_create() {
return NULL; // 空链表就是返回NULL
}
// 在链表末尾添加元素
void List_End_appendNode(ListNode** head, int newValue) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); // 创建新节点
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->value = newValue;
newNode->next = NULL;
if (*head == NULL) {
// 如果链表为空,新节点即为头节点
*head = newNode; //改变了头节点的地址
} //*head存储的是链表的头地址
else {
// 否则,遍历到链表末尾,将新节点添加进去
ListNode* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
}
//在链表开头添加元素
void List_Head_appendNode(ListNode** head, int newValue) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); // 创建新节点
if (newNode == NULL) {
printf("Memory allocation failed\n"); //判断内存是否分配成功
return;
}
newNode->value = newValue;
newNode->next = *head;
*head = newNode;
}
// 遍历链表并打印
void List_Print(ListNode* head) { //传入的参数是结构体类型的指针,也是链表开头结构体的指针,所以也可以说是传入了链表
ListNode* current = head;
while (current != NULL) {
printf("%d -> ", current->value);
current = current->next;
}
printf("NULL\n");
}
//拼接链表
void List_Link(ListNode** head_1, ListNode** head_2) {
if (head_1 == NULL || *head_1 == NULL || head_2 == NULL || *head_2 == NULL) {
// 处理空指针的情况,比如打印错误信息或设置错误代码
return;
}
ListNode* current = *head_1;
while (current->next != NULL) {
current = current->next;
}
current->next = *head_2;
}
//尾删节点
//要删除链表的最后一个节点,你需要访问倒数第二个节点(即最后一个节点的前一个节点),
// 并将其 next 指针设置为 NULL.
void List_End_Delete(ListNode** head) {
if (head == NULL || *head == NULL || (*head)->next == NULL) {
// 处理空指针的情况,比如打印错误信息或设置错误代码
return;
}
ListNode* current = *head;
ListNode* prev = NULL; // 用于追踪current的前一个节点
while (current->next != NULL) {
prev = current;
current = current->next;
}
// 此时current指向链表的最后一个节点
// prev指向链表的倒数第二个节点
// 将prev的next指针设置为NULL,从而从链表中删除最后一个节点
prev->next = NULL;
free(current);
}
//头删节点
void List_Head_Delete(ListNode** head) {
// 检查头指针是否为空或链表是否为空
if (head == NULL || *head == NULL) {
// 处理空指针或空链表的情况
printf("The list is empty"); // 这里可以选择打印错误信息或设置错误代码,但通常不需要删除操作
return;
}
// 至少有一个节点需要被删除
ListNode* first_node = *head; // 保存头节点的指针
*head = first_node->next; // 更新头指针,使其指向下一个节点
// 释放原头节点的内存
free(first_node);
// 注意:这里不需要检查 (*head)->next == NULL,因为即使链表只有一个节点,
// 在更新头指针后,head 将指向 NULL,这是正确的。
// 如果链表原本为空(即 *head == NULL),则不会执行到 free(first_node); 这行代码。
}
//清空链表
void List_Empty(ListNode** head) {
// 检查头指针是否为空或链表是否为空
if (head == NULL || *head == NULL) {
// 处理空指针或空链表的情况
printf("The list is empty"); // 这里可以选择打印错误信息或设置错误代码,但通常不需要删除操作
return;
}
ListNode* current = *head;
while (current->next != NULL) {
current->value = 0;
current = current->next;
}
}
//链表反转
void List_reversal(ListNode** head) {
ListNode* prev = NULL; // 前一个节点地址,初始化为NULL
ListNode* current = *head; // 当前节点地址,初始化为头节点
// 遍历链表,直到current为NULL
while (current != NULL) {
ListNode* next = current->next; // 保存下一个节点的指针
current->next = prev; // 反转当前节点的next指针
prev = current; // 移动prev和current指针
current = next;
}
*head = prev; // 当遍历完成时,prev将指向新的头节点
}
// 插入排序函数 ,根据value排序
void List_insertionSort(ListNode** head) {
ListNode* sorted = NULL; // 初始化一个空的已排序链表
ListNode* current = *head;
while (current != NULL) {
ListNode* nextTemp = current->next; // 保存当前节点的下一个节点
// 将当前节点插入到已排序链表中的正确位置,此时current->next会变更,不在与原链表连接
if (sorted == NULL || sorted->value >= current->value) {
// 如果已排序链表为空,或者当前节点应该插入到已排序链表的头部
current->next = sorted;
sorted = current;
}
else {
// 否则,在已排序链表中查找插入位置
ListNode* prev = NULL;
ListNode* temp = sorted;
while (temp != NULL && temp->value < current->value) {
prev = temp;
temp = temp->next;
}
prev->next = current; // 将当前节点插入到正确位置
current->next = temp;
}
current = nextTemp; // 移动到原始链表的下一个节点
}
*head = sorted; // 更新头指针
}
链表的常用函数
最新推荐文章于 2024-11-23 18:46:35 发布
243

被折叠的 条评论
为什么被折叠?



