GESP5级C++考试语法知识(六、链表(一)单链表)


🏰 第一章:什么是链表?

🎯 故事开场

在一个叫"数据王国"的地方,有两种排队方式:


🍬 队伍1:数组村

小朋友们手拉手站好,位置固定:

复制代码
[小A][小B][小C][小D]

👉 想插队?必须整体挪动!


🚂 队伍2:链表火车(今天主角!)

每个小朋友坐一节车厢,只知道"下一节是谁":

复制代码
小A → 小B → 小C → 小D

👉 插入?直接接上去!

👉 删除?跳过去就行!


🧠 第二章:链表的结构(最重要!)

🎯 单链表节点长这样:

复制代码
struct Node
{
    int data;      // 数据(小朋友的名字)
    Node* next;    // 指向下一个人
};

👉 每个节点 = 数据 + 指针(指路牌)


🏗 第三章:创建链表(搭火车!)

🎯 故事:建一列火车

复制代码
Node* head = NULL;  // 火车头(空)

// 创建第一个节点
Node* a = new Node{1, NULL};
head = a;

// 创建第二个节点
Node* b = new Node{2, NULL};
a->next = b;

// 创建第三个节点
Node* c = new Node{3, NULL};
b->next = c;

🚂 结果:

复制代码
1 → 2 → 3 → NULL

🔍 第四章:遍历链表(参观火车)

🎯 故事:列车员检查每一节车厢

复制代码
Node* p = head;

while(p != NULL)
{
    cout << p->data << " ";
    p = p->next;
}

👉 输出:

复制代码
1 2 3

➕ 第五章:插入节点(新车厢加入)

🎯 1️⃣ 头部插入(插队第一名)

复制代码
Node* newNode = new Node{0, head};
head = newNode;

🚂:

复制代码
0 → 1 → 2 → 3

🎯 2️⃣ 中间插入

👉 在 2 后面插入 99

复制代码
Node* p = head;

while(p->data != 2)
{
    p = p->next;
}

Node* newNode = new Node{99, p->next};
p->next = newNode;

🚂:

复制代码
1 → 2 → 99 → 3

❌ 第六章:删除节点(车厢拆除)

🎯 删除值为2的节点

复制代码
Node* p = head;

while(p->next != NULL && p->next->data != 2)
{
    p = p->next;
}

Node* temp = p->next;
p->next = temp->next;
delete temp;

🚂:

复制代码
1 → 3

🔄 第七章:链表反转(火车掉头!)

🎯 故事:整列火车调头!

原来:

复制代码
1 → 2 → 3

变成:

复制代码
3 → 2 → 1

🧠 核心思路(三指针)

复制代码
Node* prev = NULL;
Node* cur = head;

while(cur != NULL)
{
    Node* next = cur->next; // 保存下一节
    cur->next = prev;       // 反向
    prev = cur;             // 前进
    cur = next;
}

head = prev;

🔁 第八章:🌟用输入创建链表🌟


1、刚才我们是这样建火车的:

复制代码
Node* a = new Node{1, NULL};
Node* b = new Node{2, NULL};
Node* c = new Node{3, NULL};

👉 ❌ 问题:

数据是写死的

不能让用户输入

不符合考试要求


2、目标

👉 用户输入:

复制代码
输入:
5
1 2 3 4 5

👉 我们要创建:

复制代码
1 → 2 → 3 → 4 → 5 → NULL

3、🎯 方法:尾插法(最常用🔥)

👉 一边读输入,一边接到链表后面!


🚂 图解过程

假设输入:1 2 3


第1步:插入1

复制代码
1 → NULL

第2步:插入2

复制代码
1 → 2 → NULL

第3步:插入3

复制代码
1 → 2 → 3 → NULL

4、🚀 使用 tail(推荐🔥🔥🔥)


(1)💡 核心思想

👉 用一个指针记住"尾巴"


(2)💻 完整代码

cpp 复制代码
#include <iostream>
using namespace std;

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

int main()
{
    int n;
    cin >> n;

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

    for(int i = 0; i < n; i++)
    {
        int x;
        cin >> x;

        Node* node = new Node{x, NULL};

        if(head == NULL)
        {
            head = tail = node;
        }
        else
        {
            tail->next = node;
            tail = node;
        }
    }

    // 输出
    Node* p = head;
    while(p)
    {
        cout << p->data << " ";
        p = p->next;
    }

    return 0;
}

5、🎁 进阶写法(封装函数)

cpp 复制代码
Node* buildList(int n)
{
    Node* head = NULL;
    Node* tail = NULL;

    for(int i = 0; i < n; i++)
    {
        int x;
        cin >> x;

        Node* node = new Node{x, NULL};

        if(head == NULL)
            head = tail = node;
        else
        {
            tail->next = node;
            tail = node;
        }
    }

    return head;
}

6、🎯 三种建链方式

复制代码
1️⃣ 手写节点(学习用)
2️⃣ insertTail(基础用)
3️⃣ tail优化(考试用🔥)

🧪 第九章:完整参考代码

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* buildList(int n) {
    Node* head = NULL;
    Node* tail = NULL;

    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;

        Node* node = new Node{x, NULL};

        if (head == NULL)
            head = tail = node;
        else {
            tail->next = node;
            tail = node;
        }
    }
    return head;
}

void printList(Node* head) {
    Node* p = head;
    while (p != NULL) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

Node* reverseList(Node* head) {
    Node* prev = NULL;
    Node* cur = head;

    while (cur != NULL) {
        Node* next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }
    return prev;
}

int main() {
    int n;
    cout << "请输入链表长度: ";
    cin >> n;
    
    cout << "请输入链表元素(共" << n << "个): ";
    Node* list = buildList(n);
    
    cout << "原链表: ";
    printList(list);
    
    Node* reversed = reverseList(list);
    cout << "反转后链表: ";
    printList(reversed);
    
    return 0;
}

🎯 第十章:总结口诀

✨ 链表口诀:

复制代码
创建节点两部分:数据 + 指针
遍历链表用 while,走到 NULL 停下来
插入节点改指针,新旧连接要记清
删除节点先保存,再断开来再释放
链表反转三指针,prev cur next要分明

我们继续进入升级冒险------

🌟《链表10道经典练习题》🌟

目标:让你 真正会写、会用、会做题!


🧩 第1题:打印链表(最基础)

1、🎯 故事

你是"火车检票员",要检查每节车厢的编号。


2、🚂 图解

复制代码
1 → 2 → 3 → 4

3、💡 思路

从头走到尾,每个都打印。


4、💻 核心代码

复制代码
void printList(Node* head)
{
    Node* p = head;
    while(p != NULL)
    {
        cout << p->data << " ";
        p = p->next;
    }
}

5、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

void printList(Node* head)
{
    Node* p = head;
    while(p != NULL)
    {
        cout << p->data << " ";
        p = p->next;
    }
}

int main()
{
    // 创建链表 1→2→3→4
    Node* a = new Node{1, NULL};
    Node* b = new Node{2, NULL};
    Node* c = new Node{3, NULL};
    Node* d = new Node{4, NULL};

    a->next = b;
    b->next = c;
    c->next = d;

    Node* head = a;

    printList(head);

    return 0;
}

🧩 第2题:统计节点个数

1、🎯 故事

数一数火车有几节车厢 🚃


2、💡 思路

遍历 + 计数器


3、💻核心代码

复制代码
int count(Node* head)
{
    int cnt = 0;
    while(head)
    {
        cnt++;
        head = head->next;
    }
    return cnt;
}

4、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

int count(Node* head)
{
    int cnt = 0;
    while(head)
    {
        cnt++;
        head = head->next;
    }
    return cnt;
}

int main()
{
    Node* a = new Node{1, NULL};
    Node* b = new Node{2, NULL};
    Node* c = new Node{3, NULL};

    a->next = b;
    b->next = c;

    cout << count(a);

    return 0;
}

🧩 第3题:查找某个值

1、🎯 故事

找"3号乘客"在哪里?


2、💻核心代码

复制代码
bool find(Node* head, int x)
{
    while(head)
    {
        if(head->data == x) return true;
        head = head->next;
    }
    return false;
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

bool find(Node* head, int x)
{
    while(head)
    {
        if(head->data == x) return true;
        head = head->next;
    }
    return false;
}

int main()
{
    Node* a = new Node{1, NULL};
    Node* b = new Node{2, NULL};
    Node* c = new Node{3, NULL};

    a->next = b;
    b->next = c;

    cout << find(a, 3); // 1 表示找到

    return 0;
}

🧩 第4题:头插法建链表

1、🎯 故事

每次新乘客都插队到最前面 😄


2、💻核心代码

复制代码
Node* insertHead(Node* head, int x)
{
    return new Node{x, head};
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* insertHead(Node* head, int x)
{
    return new Node{x, head};
}

void print(Node* head)
{
    while(head)
    {
        cout << head->data << " ";
        head = head->next;
    }
}

int main()
{
    Node* head = NULL;

    head = insertHead(head, 3);
    head = insertHead(head, 2);
    head = insertHead(head, 1);

    print(head); // 1 2 3

    return 0;
}

🧩 第5题:尾插法建链表

1、🎯 故事

乘客排队上车,按顺序来


2、🚂 图解

复制代码
1 → 2 → 3

3、💻核心代码

复制代码
Node* insertTail(Node* head, int x)
{
    Node* node = new Node{x, NULL};

    if(head == NULL) return node;

    Node* p = head;
    while(p->next != NULL)
        p = p->next;

    p->next = node;
    return head;
}

4、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* insertTail(Node* head, int x)
{
    Node* node = new Node{x, NULL};

    if(head == NULL) return node;

    Node* p = head;
    while(p->next)
        p = p->next;

    p->next = node;
    return head;
}

void print(Node* head)
{
    while(head)
    {
        cout << head->data << " ";
        head = head->next;
    }
}

int main()
{
    Node* head = NULL;

    head = insertTail(head, 1);
    head = insertTail(head, 2);
    head = insertTail(head, 3);

    print(head);

    return 0;
}

🧩 第6题:删除第一个等于x的节点

1、🎯 故事

把"捣乱的乘客x"请下车 🚫


2、💻核心代码

复制代码
Node* deleteValue(Node* head, int x)
{
    if(head == NULL) return head;

    if(head->data == x)
    {
        Node* t = head;
        head = head->next;
        delete t;
        return head;
    }

    Node* p = head;
    while(p->next && p->next->data != x)
        p = p->next;

    if(p->next)
    {
        Node* t = p->next;
        p->next = t->next;
        delete t;
    }

    return head;
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* deleteValue(Node* head, int x)
{
    if(head == NULL) return head;

    if(head->data == x)
    {
        Node* t = head;
        head = head->next;
        delete t;
        return head;
    }

    Node* p = head;
    while(p->next && p->next->data != x)
        p = p->next;

    if(p->next)
    {
        Node* t = p->next;
        p->next = t->next;
        delete t;
    }

    return head;
}

void print(Node* head)
{
    while(head)
    {
        cout << head->data << " ";
        head = head->next;
    }
}

int main()
{
    Node* head = new Node{1, new Node{2, new Node{3, NULL}}};

    head = deleteValue(head, 2);

    print(head); // 1 3

    return 0;
}

🧩 第7题:反转链表

1、🎯 故事

火车全部掉头!


2、💻核心代码

复制代码
Node* reverse(Node* head)
{
    Node* prev = NULL;
    Node* cur = head;

    while(cur)
    {
        Node* next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }

    return prev;
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* reverse(Node* head)
{
    Node* prev = NULL;
    Node* cur = head;

    while(cur)
    {
        Node* next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }

    return prev;
}

void print(Node* head)
{
    while(head)
    {
        cout << head->data << " ";
        head = head->next;
    }
}

int main()
{
    Node* head = new Node{1, new Node{2, new Node{3, NULL}}};

    head = reverse(head);

    print(head); // 3 2 1

    return 0;
}

🧩 第8题:找中间节点(快慢指针)

1、🎯 故事

一个人走一步,一个人走两步 👣


2、💻核心代码

复制代码
Node* middle(Node* head)
{
    Node* slow = head;
    Node* fast = head;

    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }

    return slow;
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* middle(Node* head)
{
    Node* slow = head;
    Node* fast = head;

    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }

    return slow;
}

int main()
{
    Node* head = new Node{1, new Node{2, new Node{3, new Node{4, NULL}}}};

    Node* mid = middle(head);

    cout << mid->data; // 3

    return 0;
}

🧩 第9题:判断链表是否有环(进阶🔥)

1、🎯 故事

火车是不是绕圈了?


2、💻核心代码

复制代码
bool hasCycle(Node* head)
{
    Node* slow = head;
    Node* fast = head;

    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        if(slow == fast)
            return true;
    }
    return false;
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

bool hasCycle(Node* head)
{
    Node* slow = head;
    Node* fast = head;

    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        if(slow == fast)
            return true;
    }
    return false;
}

int main()
{
    Node* a = new Node{1, NULL};
    Node* b = new Node{2, NULL};
    Node* c = new Node{3, NULL};

    a->next = b;
    b->next = c;
    c->next = a; // 制造环

    cout << hasCycle(a); // 1

    return 0;
}

🧩 第10题:合并两个有序链表(进阶🔥🔥)

1、🎯 故事

两列有序火车合并成一列 🚄🚄

复制代码
1→3→5
2→4→6

👉 变成:

复制代码
1→2→3→4→5→6

2、💻核心代码

复制代码
Node* merge(Node* a, Node* b)
{
    Node dummy;
    Node* tail = &dummy;
    dummy.next = NULL;

    while(a && b)
    {
        if(a->data < b->data)
        {
            tail->next = a;
            a = a->next;
        }
        else
        {
            tail->next = b;
            b = b->next;
        }
        tail = tail->next;
    }

    if(a) tail->next = a;
    if(b) tail->next = b;

    return dummy.next;
}

3、💻 参考程序

cpp 复制代码
#include <iostream>
using namespace std;

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

Node* merge(Node* a, Node* b)
{
    Node dummy;
    Node* tail = &dummy;
    dummy.next = NULL;

    while(a && b)
    {
        if(a->data < b->data)
        {
            tail->next = a;
            a = a->next;
        }
        else
        {
            tail->next = b;
            b = b->next;
        }
        tail = tail->next;
    }

    if(a) tail->next = a;
    if(b) tail->next = b;

    return dummy.next;
}

void print(Node* head)
{
    while(head)
    {
        cout << head->data << " ";
        head = head->next;
    }
}

int main()
{
    Node* a = new Node{1, new Node{3, new Node{5, NULL}}};
    Node* b = new Node{2, new Node{4, new Node{6, NULL}}};

    Node* c = merge(a, b);

    print(c); // 1 2 3 4 5 6

    return 0;
}

🧠 总结:链表做题核心思路

🎯 必会5大技能

复制代码
1️⃣ 会遍历(while走)
2️⃣ 会改指针(插入/删除)
3️⃣ 会画图(非常重要!)
4️⃣ 会双指针(快慢指针)
5️⃣ 会dummy节点(高级技巧)

🎁 终极口诀

复制代码
链表问题不害怕,画图分析是关键
插入删除改指针,先连后断不出错
快慢指针找中点,环形问题也能解
反转链表三步走,prev cur next记心头

相关推荐
m0_518019481 小时前
C++与机器学习框架
开发语言·c++·算法
qq_417695052 小时前
C++中的代理模式高级应用
开发语言·c++·算法
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(十九):ADC 深度解析 —— 从模拟信号到数字转换(底层原理 + 寄存器配置)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
xiaoye-duck2 小时前
《算法题讲解指南:动态规划算法--路径问题》--5.不同路径,6.不同路径II
c++·算法·动态规划
ambition202422 小时前
最大子数组和算法全解析:从暴力枚举到动态规划优化
数据结构·c++·算法
Book思议-3 小时前
【数据结构实战】线性表的应用
c语言·数据结构·算法·链表
qq_461489333 小时前
C++与Qt图形开发
开发语言·c++·算法
x_xbx3 小时前
LeetCode:83. 删除排序链表中的重复元素
算法·leetcode·链表
小菜鸡桃蛋狗4 小时前
C++——类和对象(上)
开发语言·c++