惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
S
SegmentFault 最新的问题
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
爱范儿
爱范儿
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
DataBreaches.Net
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
D
Docker
C
Cybersecurity and Infrastructure Security Agency CISA
K
Kaspersky official blog
宝玉的分享
宝玉的分享
腾讯CDC
Google Online Security Blog
Google Online Security Blog
Recorded Future
Recorded Future
T
The Exploit Database - CXSecurity.com
T
The Blog of Author Tim Ferriss
V
V2EX
S
Securelist
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
C
CERT Recently Published Vulnerability Notes
A
Arctic Wolf
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
Y
Y Combinator Blog
P
Proofpoint News Feed
T
Tor Project blog
AWS News Blog
AWS News Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The Last Watchdog
The Last Watchdog
博客园 - 聂微东
T
Threat Research - Cisco Blogs
B
Blog
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
N
News and Events Feed by Topic
博客园 - 司徒正美
H
Help Net Security
C
Cisco Blogs
C
Check Point Blog
S
Secure Thoughts

飘雪博客

今年太惨了 - 工作记录 - 飘雪博客 房屋维修基金 - 想哪写哪 - 飘雪博客 民生银行离谱 - 想哪写哪 - 飘雪博客 遭遇催收轰炸 - 想哪写哪 - 飘雪博客 摸鱼网站-1 老男人游戏网关了 /(ㄒoㄒ)/~~ - 想哪写哪 经过我苦口婆心的劝说,孩子愿意报足球了 - 想哪写哪 - 飘雪博客 孩子近视了! - 想哪写哪 - 飘雪博客 c语言中学不会的知识点 - 想哪写哪 - 飘雪博客 给博客增加了留言邮件通知插件以及草稿箱 - 想哪写哪 - 飘雪博客 备忘:小智固件 - 想哪写哪 - 飘雪博客
c语言不懂的知识点2——链表 - 想哪写哪 - 飘雪博客
2026-03-18 · via 飘雪博客

链表是一种存储结构,在物理存储单元上表现的是非连续、非顺序的一种存储结构。常见的链表有单向链表、双向链表、循环链表等。

单向链表

每个节点之间通过地址的方式进行单向链接,头部指针指向首个节点的内存地址,首节点中存储下一个的地址,以此类推,直至末尾节点后面没有节点时,末尾节点指向NULL。

双向链表

每个节点之间通过地址的方式进行双向链接,头部指针指向首个节点的内存地址,首节点中存储了两个地址,分别是:下一个节点的地址、前一个节点的地址(首节点前面没有则为NULL),以此类推,直至最后一个节点后面没有节点时,最后一个节点存储了倒数第2个节点的地址和空节点NULL。

循环链表

同单向链表类似,每个节点之间通过地址的方式进行单向链接,但末尾的节点不再指向NULL(空节点),而是指向首节点。

单向链表的实现

实现步骤分析:

  1. .h头文件中定义节点数据结构体;

  2. .h头文件中分别声明链表的增、删、改、查函数;

    1. 声明链表的添加函数;

    2. 声明链表的输出函数;

    3. 声明链表的删除函数;

    4. 声明链表的修改函数;

  1. .c文件中创建头部指针;

  2. .c文件中实现.h文件中分别实现的增、删、改、查函数;

    1. 实现链表的添加函数;

    2. 实现链表的输出函数;

    3. 实现链表的删除函数;

    4. 实现链表的修改函数;

实现代码如下:


LinkedList.h

#ifndef __LINKED_LIST_H__
#define __LINKED_LIST_H__

// 1. 在`.h`头文件中定义节点数据结构体;
typedef struct LinkedListNode {
    int data;
    struct LinkedListNode* next;
} NODE;

// 2. 在.h头文件中分别声明链表的增、删、改、查函数;

// a. 声明链表的添加函数;
int add_node(int data);	 

// b. 声明链表的输出函数;
void print_all_node();

// c. 声明链表的删除函数;
int delete_node(int data);

// d. 声明链表的修改函数;
int update_node(int old_data, int new_data);

#endif

LinkedList.c

#include "LinkedList.h"
#include <stdlib.h>
#include <stdio.h>

// 3. 在.c文件中创建头部指针;
struct LinkedListNode* head;

// 4. 在.c文件中实现.h文件中分别实现的增、删、改、查函数;

// a. 实现链表的添加函数;
int add_node(int data) {
    NODE* p_new_node = (NODE*)malloc(sizeof(NODE));
    p_new_node->data = data;
    p_new_node->next = NULL;

    if (head == NULL) {
        // 当前头部指针为NULL,没有节点,新节点设置为首节点
        head = p_new_node;
    } else {
        NODE* current = head;
        while(current->next != NULL) {
            // 当前节点的下一个节点不为NULL时,让当前节点向后移动一个节点
            current = current->next;
        }
        // 当前节点的下一个节点为NULL,已经到末尾,将新节点添加进去
        current->next = p_new_node;
    }
    return 1;
}

// b. 实现链表的输出函数;
void print_all_node() {
    NODE* current = head;
    while(current != NULL) {
        printf("当前节点地址:%#p, 值为:%d\n", current, current->data);
        current = current->next;
    }
}

// c. 实现链表的删除函数;
int delete_node(int data) {
    if (head == NULL) {
        return 0;
    }

    // 查找节点
    NODE* current = head;
    NODE* previous;
    while(current != NULL && current->data != data) {
        previous = current;
        current = current->next;
    }

    if (previous == NULL) {
        // 第一个节点就找到了
        head = current->next;
        return 1;
    }

    if (current == NULL) {
        // 没找到,删除失败
        return 0;
    }

    // 删除当前节点:前一个节点直接指向当前节点的下一个节点
    previous->next = current->next;
    // 释放当前节点的内存
    free(current);
    return 1;
}

// d. 实现链表的修改函数;
int update_node(int old_data, int new_data) {
    if(head == NULL) {
        return 0;
    }

    NODE* current = head;
    while(current != NULL) {
        if (current->data == old_data) {
            current->data = new_data;
            break;
        }
        current = current->next;
    }
    return 1;
}

main.c

#include <stdio.h>
#include "LinkedList.h"

int main() {

    add_node(1);
    add_node(2);
    add_node(3);
    add_node(4);
    add_node(5);
    print_all_node();

    printf("----------------------------\n");

    delete_node(2);
    print_all_node();
    
    printf("----------------------------\n");

    update_node(3, 10);
    print_all_node();
    return 0;
}