数据结构:链表-单向链表篇

链表,它由一系列节点(结构体) 组成,每个节点包含数据字段和指针 ,节点和节点之间通过指针连接在一起。与数组不同,链表中的元素在内存中不是连续存储的,而是通过指针连接在一起。

cpp 复制代码
// 单向链表节点定义
struct Node {
    int data;           // 数据字段
    struct Node* next;  // 指向下一个节点的指针
};

单向链表

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构
struct Node {
    int data;
    struct Node* next;
};

// 创建新节点的函数
struct Node* createNode(int data) {
    // 分配内存
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    
    // 检查内存分配是否成功
    if (newNode == NULL) {
        printf("内存分配失败!\n");
        exit(1);
    }
    
    // 初始化节点数据
    newNode->data = data;
    newNode->next = NULL;
    
    return newNode;
}

在链表头部插入节点

cpp 复制代码
// 在链表头部插入节点
struct Node* insertAtBeginning(struct Node* head, int data) {
    // 创建新节点
    struct Node* newNode = createNode(data);
    
    // 将新节点的next指向当前的头节点
    newNode->next = head;
    
    // 更新头节点为新节点
    return newNode;
}

在链表尾部插入节点

cpp 复制代码
// 在链表尾部插入节点
struct Node* insertAtEnd(struct Node* head, int data) {
    // 创建新节点
    struct Node* newNode = createNode(data);
    
    // 如果链表为空,新节点就是头节点
    if (head == NULL) {
        return newNode;
    }
    
    // 找到链表的最后一个节点
    struct Node* current = head;
    while (current->next != NULL) {
        current = current->next;
    }
    
    // 将最后一个节点的next指向新节点
    current->next = newNode;
    
    // 返回头节点
    return head;
}

在指定位置插入节点

cpp 复制代码
// 在指定位置插入节点
struct Node* insertAtPosition(struct Node* head, int data, int position) {
    // 如果位置是1,相当于在头部插入
    if (position == 1) {
        return insertAtBeginning(head, data);
    }
    
    // 创建新节点
    struct Node* newNode = createNode(data);
    
    // 找到要插入位置的前一个节点
    struct Node* current = head;
    for (int i = 1; i < position - 1 && current != NULL; i++) {
        current = current->next;
    }
    
    // 检查位置是否有效
    if (current == NULL) {
        printf("位置无效!\n");
        free(newNode);
        return head;
    }
    
    // 插入新节点
    newNode->next = current->next;
    current->next = newNode;
    
    return head;
}

删除节点

cpp 复制代码
// 删除指定值的第一个节点
struct Node* deleteNode(struct Node* head, int key) {
    // 如果链表为空,直接返回
    if (head == NULL) {
        return NULL;
    }
    
    // 如果头节点就是要删除的节点
    if (head->data == key) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }
    
    // 查找要删除的节点
    struct Node* current = head;
    while (current->next != NULL && current->next->data != key) {
        current = current->next;
    }
    
    // 如果找到了要删除的节点
    if (current->next != NULL) {
        struct Node* temp = current->next;
        current->next = temp->next;
        free(temp);
    }
    
    return head;
}

查找节点

cpp 复制代码
// 查找指定值的节点
struct Node* searchNode(struct Node* head, int key) {
    struct Node* current = head;
    
    // 遍历链表
    while (current != NULL) {
        if (current->data == key) {
            return current;  // 找到节点,返回指针
        }
        current = current->next;
    }
    
    return NULL;  // 未找到节点
}

打印链表

cpp 复制代码
// 打印链表的所有节点
void printList(struct Node* head) {
    struct Node* current = head;
    
    printf("链表内容: ");
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

释放链表

cpp 复制代码
// 释放链表的所有节点
void freeList(struct Node* head) {
    struct Node* current = head;
    struct Node* next;
    
    while (current != NULL) {
        next = current->next;  // 保存下一个节点
        free(current);         // 释放当前节点
        current = next;        // 移动到下一个节点
    }
}
cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构
struct Node {
    int data;
    struct Node* next;
};

// 创建新节点
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("内存分配失败!\n");
        exit(1);
    }
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 在链表头部插入节点
struct Node* insertAtBeginning(struct Node* head, int data) {
    struct Node* newNode = createNode(data);
    newNode->next = head;
    return newNode;
}

// 在链表尾部插入节点
struct Node* insertAtEnd(struct Node* head, int data) {
    struct Node* newNode = createNode(data);
    
    if (head == NULL) {
        return newNode;
    }
    
    struct Node* current = head;
    while (current->next != NULL) {
        current = current->next;
    }
    
    current->next = newNode;
    return head;
}

// 在指定位置插入节点
struct Node* insertAtPosition(struct Node* head, int data, int position) {
    if (position == 1) {
        return insertAtBeginning(head, data);
    }
    
    struct Node* newNode = createNode(data);
    
    struct Node* current = head;
    for (int i = 1; i < position - 1 && current != NULL; i++) {
        current = current->next;
    }
    
    if (current == NULL) {
        printf("位置无效!\n");
        free(newNode);
        return head;
    }
    
    newNode->next = current->next;
    current->next = newNode;
    
    return head;
}

// 删除指定值的第一个节点
struct Node* deleteNode(struct Node* head, int key) {
    if (head == NULL) {
        return NULL;
    }
    
    if (head->data == key) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }
    
    struct Node* current = head;
    while (current->next != NULL && current->next->data != key) {
        current = current->next;
    }
    
    if (current->next != NULL) {
        struct Node* temp = current->next;
        current->next = temp->next;
        free(temp);
    }
    
    return head;
}

// 查找指定值的节点
struct Node* searchNode(struct Node* head, int key) {
    struct Node* current = head;
    
    while (current != NULL) {
        if (current->data == key) {
            return current;
        }
        current = current->next;
    }
    
    return NULL;
}

// 打印链表
void printList(struct Node* head) {
    struct Node* current = head;
    
    printf("链表内容: ");
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// 释放链表
void freeList(struct Node* head) {
    struct Node* current = head;
    struct Node* next;
    
    while (current != NULL) {
        next = current->next;
        free(current);
        current = next;
    }
}

// 获取链表长度
int getLength(struct Node* head) {
    int count = 0;
    struct Node* current = head;
    
    while (current != NULL) {
        count++;
        current = current->next;
    }
    
    return count;
}

// 反转链表
struct Node* reverseList(struct Node* head) {
    struct Node* prev = NULL;
    struct Node* current = head;
    struct Node* next = NULL;
    
    while (current != NULL) {
        next = current->next;  // 保存下一个节点
        current->next = prev;  // 反转当前节点的指针
        prev = current;        // 移动prev指针
        current = next;        // 移动current指针
    }
    
    return prev;  // 新的头节点
}

int main() {
    struct Node* head = NULL;
    
    // 在链表尾部插入节点
    head = insertAtEnd(head, 10);
    head = insertAtEnd(head, 20);
    head = insertAtEnd(head, 30);
    
    printf("初始链表:\n");
    printList(head);
    
    // 在链表头部插入节点
    head = insertAtBeginning(head, 5);
    printf("\n在头部插入5后:\n");
    printList(head);
    
    // 在指定位置插入节点
    head = insertAtPosition(head, 15, 3);
    printf("\n在位置3插入15后:\n");
    printList(head);
    
    // 删除节点
    head = deleteNode(head, 20);
    printf("\n删除值为20的节点后:\n");
    printList(head);
    
    // 查找节点
    struct Node* found = searchNode(head, 15);
    if (found != NULL) {
        printf("\n找到值为15的节点\n");
    } else {
        printf("\n未找到值为15的节点\n");
    }
    
    // 获取链表长度
    printf("\n链表长度: %d\n", getLength(head));
    
    // 反转链表
    head = reverseList(head);
    printf("\n反转链表后:\n");
    printList(head);
    
    // 释放链表
    freeList(head);
    
    return 0;
}
相关推荐
天赐学c语言2 小时前
1.20 - x的平方根 && vector的扩容机制以及删除元素是否会释放内存
c++·算法·leecode
52Hz1183 小时前
力扣24.两两交换链表中的节点、25.K个一组反转链表
算法·leetcode·链表
老鼠只爱大米3 小时前
LeetCode经典算法面试题 #160:相交链表(双指针法、长度差法等多种方法详细解析)
算法·leetcode·链表·双指针·相交链表·长度差法
ValhallaCoder3 小时前
Day53-图论
数据结构·python·算法·图论
老鼠只爱大米3 小时前
LeetCode经典算法面试题 #84:柱状图中最大的矩形(单调栈、分治法等四种方法详细解析)
算法·leetcode·动态规划·单调栈·分治法·柱状图最大矩形
C雨后彩虹3 小时前
羊、狼、农夫过河
java·数据结构·算法·华为·面试
重生之后端学习4 小时前
19. 删除链表的倒数第 N 个结点
java·数据结构·算法·leetcode·职场和发展
aini_lovee4 小时前
严格耦合波(RCWA)方法计算麦克斯韦方程数值解的MATLAB实现
数据结构·算法·matlab
安特尼4 小时前
推荐算法手撕集合(持续更新)
人工智能·算法·机器学习·推荐算法
鹿角片ljp4 小时前
力扣14.最长公共前缀-纵向扫描法
java·算法·leetcode