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

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

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;
}
相关推荐
ZhengEnCi23 分钟前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
Flynn Liang43 分钟前
RAG 答非所问/幻觉怎么破?Spring AI QuestionAnswerAdvisor 召回优化实战(TopK/重排/混合检索)
人工智能·算法·spring·rag·幻觉·springai
liminla!1 小时前
SQL 从入门到进阶:语法速查与实战练习(完整优化版)
数据库·sql·算法
维克兜率天2 小时前
【维克】指数调整:哪些股票会被“强制买入“?
人工智能·python·算法
罗西的思考3 小时前
【轻量化复刻大模型】线性注意力交互式演示
人工智能·算法·机器学习
神也畏惧菠萝3 小时前
Day08 Python流程控制从入门到上瘾:if/match/while/for四件套,从B站登录一路打到猜数字游戏
python·算法·数据存储·for·while·if·ifelse
揽星河..3 小时前
【C语言】分支和循环
c语言·c++·算法
Fuyo_11195 小时前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
jktantan5 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript