C语言单链表增删查改

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值