C语言链表学习笔记

C语言链表学习笔记


目录

  • 链表的基本概念
  • 静态链表的创建
  • 动态链表的创建
  • 链表的插入操作
  • 链表的删除操作
  • 链表的查找与遍历
  • 总结

链表的基本概念

1. 什么是链表?

  • 链表:一种动态数据结构,通过指针将多个节点连接成链式结构。
  • 核心组成
    • 节点:包含数据域(存储数据)和指针域(指向下一个节点)。
    • 头指针:指向链表的第一个节点。

2. 节点结构体定义

struct Node {
    int data;          // 数据域
    struct Node* next; // 指针域(指向下一个节点)
};

3. 链表的特点

  • 动态内存分配:节点内存按需分配(malloc)和释放(free)。
  • 灵活性:长度可动态调整,插入/删除效率高。

静态链表的创建

示例:手动创建3个节点的链表

#include 

struct Node {
    int data;
    struct Node* next;
};

int main() {
    // 定义3个节点
    struct Node a, b, c;
    struct Node* head; // 头指针

    // 初始化数据
    a.data = 10;
    b.data = 20;
    c.data = 30;

    // 连接节点
    head = &a;     // 头指针指向第一个节点
    a.next = &b;   // a的下一个节点是b
    b.next = &c;   // b的下一个节点是c
    c.next = NULL; // 链表结束

    // 遍历链表
    struct Node* p = head;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    // 输出:10 20 30
    return 0;
}

动态链表的创建

1. 动态分配内存函数

  • malloc:分配内存,返回地址。
  • free:释放内存。

2. 创建动态链表函数

#include 
#include 

struct Node {
    int data;
    struct Node* next;
};

// 创建新节点
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 动态创建链表(尾插法)
struct Node* createLinkedList(int values[], int n) {
    struct Node* head = NULL;
    struct Node* tail = NULL;

    for (int i = 0; i < n; i++) {
        struct Node* newNode = createNode(values[i]);
        if (head == NULL) {
            head = tail = newNode; // 第一个节点
        } else {
            tail->next = newNode;  // 尾节点指向新节点
            tail = newNode;        // 更新尾节点
        }
    }
    return head;
}

链表的插入操作

1. 头插法(插入到链表头部)

struct Node* insertAtHead(struct Node* head, int data) {
    struct Node* newNode = createNode(data);
    newNode->next = head;
    return newNode; // 新头节点
}

2. 尾插法(插入到链表尾部)

struct Node* insertAtTail(struct Node* head, int data) {
    struct Node* newNode = createNode(data);
    if (head == NULL) {
        return newNode; // 链表为空时直接返回新节点
    }

    struct Node* p = head;
    while (p->next != NULL) {
        p = p->next; // 找到尾节点
    }
    p->next = newNode;
    return head;
}

3. 中间插入(插入到指定位置)

struct Node* insertAtMiddle(struct Node* head, int pos, int data) {
    struct Node* newNode = createNode(data);
    struct Node* p = head;

    // 找到插入位置的前一个节点
    for (int i = 0; i < pos - 1 && p != NULL; i++) {
        p = p->next;
    }

    if (p == NULL) return head; // 位置无效
    newNode->next = p->next;
    p->next = newNode;
    return head;
}

链表的删除操作

删除指定值的节点

struct Node* deleteNode(struct Node* head, int data) {
    if (head == NULL) return NULL;

    // 删除头节点
    if (head->data == data) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }

    struct Node* p = head;
    while (p->next != NULL && p->next->data != data) {
        p = p->next;
    }

    if (p->next != NULL) {
        struct Node* temp = p->next;
        p->next = temp->next;
        free(temp);
    }
    return head;
}

链表的查找与遍历

1. 查找节点

struct Node* findNode(struct Node* head, int data) {
    struct Node* p = head;
    while (p != NULL) {
        if (p->data == data) {
            return p; // 找到节点
        }
        p = p->next;
    }
    return NULL; // 未找到
}

2. 遍历链表

void printLinkedList(struct Node* head) {
    struct Node* p = head;
    while (p != NULL) {
        printf("%d -> ", p->data);
        p = p->next;
    }
    printf("NULL\n");
}

总结

链表的核心操作

  1. 创建:静态或动态分配内存。
  2. 插入:头插、尾插、中间插入。
  3. 删除:调整指针并释放内存。
  4. 遍历:从头指针开始逐个访问节点。

链表的优点

  • 动态内存管理,无需预先分配空间。
  • 插入/删除高效(时间复杂度O(1)或O(n))。

注意事项

  • 内存泄漏:使用free释放不再需要的节点。
  • 空指针判断:操作前检查链表是否为空。

练习题

  1. 实现一个函数,将链表逆序(头节点变尾节点,尾节点变头节点)。
  2. 编写代码,合并两个有序链表为一个有序链表。

你可能感兴趣的:(c语言,数据结构,c语言,链表,学习)