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

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

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;
}
相关推荐
ss2732 小时前
ConcurrentHashMap:扩容机制与size()方法
算法·哈希算法
2401_860319522 小时前
在React Native鸿蒙跨平台开发中实现一个冒泡排序算法并将其应用于数据排序,如何进行复制数组以避免直接修改状态中的数组
javascript·算法·react native·react.js·harmonyos
im_AMBER2 小时前
Leetcode 72 数组列表中的最大距离
c++·笔记·学习·算法·leetcode
编程饭碗2 小时前
【Java循环】
java·服务器·算法
曾几何时`2 小时前
归并排序(一)
数据结构·算法·leetcode
CoovallyAIHub4 小时前
何必先OCR再LLM?视觉语言模型直接读图,让百页长文档信息不丢失
深度学习·算法·计算机视觉
CoovallyAIHub4 小时前
NAN-DETR:集中式噪声机制如何让检测更“团结”?
深度学习·算法·计算机视觉
CoovallyAIHub4 小时前
火箭工程大学多模态遥感检测新框架MROD-YOLO:如何将小目标检测精度提升至77.9%?
深度学习·算法·计算机视觉
CoovallyAIHub4 小时前
未来物体检测趋势:需要关注的 7 个关键问题
深度学习·算法·计算机视觉