结构体与链表

结构体与链表

在 C 语言中,结构体是一种用户自定义的数据类型,它可以把不同类型的数据组合在一起,形成一个整体。

struct Node {

int data;

struct Node *next;

};

这段代码定义了一个叫 Node 的结构体,它有两个成员:

  • int data:用来存储实际的数据,比如整数。
  • struct Node *next:是一个指针,指向下一个 Node 类型的结构体。
    结构体的内存布局
    当我们定义了一个 struct Node,编译器会为它分配一块连续的内存空间,大小等于所有成员占用空间之和。
    假设 int 占 4 字节,指针也占 8 字节(64位系统),那么每个 Node 节点总共占 12 字节(或更多,因对齐规则可能增加)。

如何创建链表节点

静态创建

struct Node node1;

struct Node node2;

struct Node node3;

struct Node node4;

node1.data = 1;

node2.data = 2;

node3.data = 3;

node4.data = 4;

node1.next = &node2;

node2.next = &node3;

node3.next = &node4;

  • 这里是直接在栈上声明变量,四个 Node 对象都存放在程序的栈区。
  • 每个节点有名字(如 node1),可以通过名字访问。
  • 使用 &node2 获取 node2 的地址,赋值给 node1.next,就建立了连接。
    动态创建
    struct Node *node1 = (struct Node *)malloc(sizeof(struct Node));
    struct Node *node2 = (struct Node *)malloc(sizeof(struct Node));
    // ... 其他节点
  • 使用 malloc() 在堆(heap) 上申请内存。
  • 返回的是一个指向该内存的指针,所以我们必须用指针接收。
  • 每个节点都是独立申请的,可以随时增删。
    起别名
    typedef struct Node {
    int data;
    struct Node *next;
    } Node, LinkNode, *sNode;
    typedef struct Node {...} Node;
    给 struct Node 起了个别名 Node,以后可以直接写 Node 而不用写 struct Node。比如:Node node1; 就等价于 struct Node node1;
    LinkNode 是另一个别名可以当作 Node 的别名使用,用于命名一致性。
    *sNode 是指针类型的别名,sNode 表示"指向 Node 结构体的指针"
    所以 sNode node4; 相当于 struct Node *node4;
    链接链表
    node1->data = 1;
    node2->data = 2;
    node3->data = 3;
    node4->data = 4;

node1->next = node2;

node2->next = node3;

node3->next = node4;

node1 → node2 → node3 → node4 → NULL

内存地址: 0x1000 0x2000 0x3000 0x4000

±---------±---------±---------±---------+

| data=1 | next=0x2000| data=2 | next=0x3000| ...

±---------±---------±---------±---------+

遍历读取链表

c 复制代码
void printList(Node *head) {
    for (Node *cur = head; cur != NULL; cur = cur->next) {
        printf("%d", cur->data);
        if (cur->next != NULL) {
            printf("->");
        }
    }
    printf("\n");
}

插入/删除链表

插入链表:

c 复制代码
int insertAt(Node **head, int index, int value) {
    int len = getListLen(*head);
    
    if (index < 0 || index > len) {
        return -1; // 插入失败
    }

    Node *newNode = (Node *)malloc(sizeof(Node));
    if (!newNode) {
        return -1;
    }
    newNode->data = value;

    if (index == 0) {
        newNode->next = *head;
        *head = newNode;
    } else {
        Node *prev = *head;
        for (int i = 0; i < index - 1; i++) {
            prev = prev->next;
        }
        newNode->next = prev->next;
        prev->next = newNode;
    }

    return 0;
}

这里传参需要二维指针是因为需要修改指针指向,若一维指针只是拷贝传递。

删除链表:

c 复制代码
// 删除第一个值为 data 的节点
void delList(Node **head, int data) {
    if (*head == NULL) return;

    // 如果要删除的是头节点
    if ((*head)->data == data) {
        Node *temp = *head;
        *head = (*head)->next;
        free(temp);
        return;
    }

    Node *cur = *head;
    while (cur->next != NULL) {
        if (cur->next->data == data) {
            Node *temp = cur->next;
            cur->next = cur->next->next;
            free(temp);
            return; // 只删第一个匹配项
        }
        cur = cur->next;
    }
}

双向链表

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

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

// 获取链表长度
int getListLen(Node *head) {
    int i = 0;
    for (Node *cur = head; cur != NULL; cur = cur->next) {
        i++;
    }
    return i;
}

int insertAt(Node **head, int index, int value) {
    int len = getListLen(*head);
    
    if (index < 0 || index > len) {
        return -1;
    }

    Node *newNode = (Node *)malloc(sizeof(Node));
    if (!newNode) {
        return -1;
    }
    newNode->data = value;
    newNode->next = NULL;
    newNode->prev = NULL;

    if (index == 0) {
        newNode->next = *head;
        if (*head != NULL) {
            (*head)->prev = newNode;
        }
        *head = newNode;
    } else {
        Node *cur = *head;
        for (int i = 0; i < index; i++) {
            cur = cur->next;
        }
        newNode->next = cur;
        newNode->prev = cur->prev;
        cur->prev->next = newNode;
        cur->prev = newNode;
    }

    return 0;
}

// 输出链表
void printList(Node *head) {
    for (Node *cur = head; cur != NULL; cur = cur->next) {
        printf("%d", cur->data);
        if (cur->next != NULL) {
            printf("->");
        }
    }
    printf("\n");
}


// 删除第一个值为 data 的节点
void delList(Node *head, int data) {
    if (head == NULL) return;

    Node *cur = head;
    while (cur != NULL) {
        if (cur->data == data) {
            if (cur->prev != NULL) {
                cur->prev->next = cur->next;
            } else {
                head = cur->next; // 删除头节点
            }
            if (cur->next != NULL) {
                cur->next->prev = cur->prev;
            }
            free(cur);
            return;
        }
        cur = cur->next;
    }
}

int main() {
    const int N = 4;
    int values[N] = {10, 20, 30, 40};

    Node *head = NULL;
    Node *tail = NULL;

    // 使用头插法
    for (int i = 0; i < N; i++) {
        Node *newNode = (Node *)malloc(sizeof(Node));
        if (!newNode) {
            return -1;
        }
        newNode->data = values[i];
        newNode->next = NULL;
        newNode->prev = tail;

        if (head == NULL) {
            head = tail = newNode;
        } else {
            ;
            tail = newNode;
        }
    }

    int len = getListLen(head);
    printf("链表长度: %d\n", len);

    // 插入
    printf("index=2 ,99");
    if (insertAt(&head, 2, 99) == 0) {
        printf("插入后: ");
        printList(head);
    }

    // 删除
    printf("请输入要删除的数据: ");
    int data;
    scanf("%d", &data);
    delList(head, data);
    printf("删除后: ");
    printList(head);
    return 0;
}
相关推荐
独好紫罗兰4 分钟前
对python的再认识-基于数据结构进行-a004-列表-实用事务
开发语言·数据结构·python
不穿格子的程序员7 分钟前
从零开始刷算法——贪心篇1:跳跃游戏1 + 跳跃游戏2
算法·游戏·贪心
大江东去浪淘尽千古风流人物9 分钟前
【SLAM新范式】几何主导=》几何+学习+语义+高效表示的融合
深度学习·算法·slam
铉铉这波能秀17 分钟前
LeetCode Hot100数据结构背景知识之列表(List)Python2026新版
数据结构·leetcode·list
重生之我是Java开发战士23 分钟前
【优选算法】模拟算法:替换所有的问号,提莫攻击,N字形变换,外观数列,数青蛙
算法
仟濹29 分钟前
算法打卡 day1 (2026-02-06 周四) | 算法: DFS | 1_卡码网98 可达路径 | 2_力扣797_所有可能的路径
算法·leetcode·深度优先
yang)30 分钟前
欠采样时的相位倒置问题
算法
历程里程碑33 分钟前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
A尘埃35 分钟前
物流公司配送路径动态优化(Q-Learning算法)
算法
天若有情67336 分钟前
【自研实战】轻量级ASCII字符串加密算法:从设计到落地(防查岗神器版)
网络·c++·算法·安全·数据安全·加密