#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// 定义链表节点结构
typedef struct StringNode {
char* data; // 字符串数据
struct StringNode* next; // 指向下一个节点的指针
} StringNode;
// 创建新节点
StringNode* createNode(const char* data) {
StringNode* newNode = (StringNode*)malloc(sizeof(StringNode));
if (newNode == NULL) {
printf("内存分配失败!\n");
return NULL;
}
// 为字符串数据分配内存并复制内容
size_t dataLength = strlen(data) + 1;
newNode->data = (char*)malloc(dataLength);
if (newNode->data == NULL) {
printf("内存分配失败!\n");
free(newNode);
return NULL;
}
// 使用安全的字符串复制函数
strcpy_s(newNode->data, dataLength, data);
newNode->next = NULL;
return newNode;
}
// 在链表头部插入节点
void insertAtHead(StringNode** head, const char* data) {
StringNode* newNode = createNode(data);
if (newNode == NULL) return;
newNode->next = *head;
*head = newNode;
printf("在头部插入节点 '%s' 成功\n", data);
}
// 在链表尾部插入节点
void insertAtTail(StringNode** head, const char* data) {
StringNode* newNode = createNode(data);
if (newNode == NULL) return;
if (*head == NULL) {
*head = newNode;
} else {
StringNode* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
printf("在尾部插入节点 '%s' 成功\n", data);
}
// 在指定位置插入节点
void insertAtPosition(StringNode** head, const char* data, int position) {
if (position < 0) {
printf("位置不能为负数!\n");
return;
}
if (position == 0) {
insertAtHead(head, data);
return;
}
StringNode* newNode = createNode(data);
if (newNode == NULL) return;
StringNode* temp = *head;
for (int i = 0; i < position - 1 && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("指定位置超出链表长度,插入失败\n");
free(newNode->data);
free(newNode);
return;
}
newNode->next = temp->next;
temp->next = newNode;
printf("在位置 %d 插入节点 '%s' 成功\n", position, data);
}
// 删除头部节点
void deleteAtHead(StringNode** head) {
if (*head == NULL) {
printf("链表为空,删除失败\n");
return;
}
StringNode* temp = *head;
*head = (*head)->next;
printf("删除头部节点 '%s' 成功\n", temp->data);
free(temp->data);
free(temp);
}
// 删除尾部节点
void deleteAtTail(StringNode** head) {
if (*head == NULL) {
printf("链表为空,删除失败\n");
return;
}
if ((*head)->next == NULL) {
printf("删除尾部节点 '%s' 成功\n", (*head)->data);
free((*head)->data);
free(*head);
*head = NULL;
return;
}
StringNode* temp = *head;
while (temp->next->next != NULL) {
temp = temp->next;
}
printf("删除尾部节点 '%s' 成功\n", temp->next->data);
free(temp->next->data);
free(temp->next);
temp->next = NULL;
}
// 删除指定位置的节点
void deleteAtPosition(StringNode** head, int position) {
if (*head == NULL) {
printf("链表为空,删除失败\n");
return;
}
if (position < 0) {
printf("位置不能为负数!\n");
return;
}
if (position == 0) {
deleteAtHead(head);
return;
}
StringNode* temp = *head;
for (int i = 0; i < position - 1 && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL || temp->next == NULL) {
printf("指定位置超出链表长度,删除失败\n");
return;
}
StringNode* nodeToDelete = temp->next;
temp->next = temp->next->next;
printf("删除位置 %d 的节点 '%s' 成功\n", position, nodeToDelete->data);
free(nodeToDelete->data);
free(nodeToDelete);
}
// 删除指定值的节点
void deleteByValue(StringNode** head, const char* value) {
if (*head == NULL) {
printf("链表为空,删除失败\n");
return;
}
// 如果头节点就是要删除的节点
if (strcmp((*head)->data, value) == 0) {
deleteAtHead(head);
return;
}
StringNode* temp = *head;
while (temp->next != NULL && strcmp(temp->next->data, value) != 0) {
temp = temp->next;
}
if (temp->next == NULL) {
printf("未找到值为 '%s' 的节点\n", value);
return;
}
StringNode* nodeToDelete = temp->next;
temp->next = temp->next->next;
printf("删除值为 '%s' 的节点成功\n", value);
free(nodeToDelete->data);
free(nodeToDelete);
}
// 查找节点
bool searchNode(StringNode* head, const char* value) {
StringNode* temp = head;
int position = 0;
while (temp != NULL) {
if (strcmp(temp->data, value) == 0) {
printf("找到值为 '%s' 的节点,位置为 %d\n", value, position);
return true;
}
temp = temp->next;
position++;
}
printf("未找到值为 '%s' 的节点\n", value);
return false;
}
// 修改节点值
void updateNode(StringNode* head, const char* oldValue, const char* newValue) {
StringNode* temp = head;
int position = 0;
while (temp != NULL) {
if (strcmp(temp->data, oldValue) == 0) {
// 释放旧内存,分配新内存
free(temp->data);
size_t newLength = strlen(newValue) + 1;
temp->data = (char*)malloc(newLength);
if (temp->data == NULL) {
printf("内存分配失败!\n");
return;
}
// 使用安全的字符串复制函数
strcpy_s(temp->data, newLength, newValue);
printf("已将位置 %d 的节点值从 '%s' 修改为 '%s'\n", position, oldValue, newValue);
return;
}
temp = temp->next;
position++;
}
printf("未找到值为 '%s' 的节点,修改失败\n", oldValue);
}
// 修改指定位置的节点值
void updateNodeAtPosition(StringNode* head, int position, const char* newValue) {
if (position < 0) {
printf("位置不能为负数!\n");
return;
}
StringNode* temp = head;
for (int i = 0; i < position && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("指定位置超出链表长度,修改失败\n");
return;
}
char* oldValue = temp->data;
// 释放旧内存,分配新内存
free(temp->data);
size_t newLength = strlen(newValue) + 1;
temp->data = (char*)malloc(newLength);
if (temp->data == NULL) {
printf("内存分配失败!\n");
return;
}
// 使用安全的字符串复制函数
strcpy_s(temp->data, newLength, newValue);
printf("已将位置 %d 的节点值从 '%s' 修改为 '%s'\n", position, oldValue, newValue);
}
// 打印链表
void printList(StringNode* head) {
if (head == NULL) {
printf("链表为空\n");
return;
}
printf("链表内容: ");
StringNode* temp = head;
while (temp != NULL) {
printf("'%s' -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
// 获取链表长度
int getLength(StringNode* head) {
int length = 0;
StringNode* temp = head;
while (temp != NULL) {
length++;
temp = temp->next;
}
return length;
}
// 释放链表内存
void freeList(StringNode** head) {
StringNode* temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp->data);
free(temp);
}
printf("链表内存已释放\n");
}
// 主函数 - 测试字符串链表操作
int main() {
StringNode* head = NULL;
printf("=== 字符串链表操作演示 ===\n\n");
// 插入操作
printf("1. 插入节点:\n");
insertAtHead(&head, "苹果");
insertAtTail(&head, "香蕉");
insertAtTail(&head, "橙子");
insertAtPosition(&head, "葡萄", 1);
insertAtPosition(&head, "西瓜", 3);
printList(head);
printf("当前链表长度: %d\n\n", getLength(head));
// 查找操作
printf("2. 查找节点:\n");
searchNode(head, "葡萄");
searchNode(head, "芒果");
printf("\n");
// 修改操作
printf("3. 修改节点:\n");
updateNode(head, "香蕉", "草莓");
updateNodeAtPosition(head, 2, "菠萝");
printList(head);
printf("\n");
// 删除操作
printf("4. 删除节点:\n");
deleteAtHead(&head);
deleteAtTail(&head);
deleteByValue(&head, "葡萄");
deleteAtPosition(&head, 1);
printList(head);
printf("当前链表长度: %d\n\n", getLength(head));
// 释放链表
freeList(&head);
return 0;
}
C语言单链表增删查改
于 2025-09-02 06:21:55 首次发布
1567

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



