数据结构:单链表的实现详解

目录

  1. 单链表的结构定义

  2. 初始化链表

  3. 求链表长度

  4. 按序号查找节点

  5. 按值查找节点

  6. 插入节点

  7. 删除节点

  8. 头插法构建链表

  9. 尾插法构建链表

  10. 完整代码与总结


1. 单链表的结构定义

单链表的每个节点包含两部分:

  • 数据域:存储节点的值(这里是 int 类型)。

  • 指针域:指向下一个节点的地址。

typedef struct LNode {
    int data;            // 数据域
    struct LNode *next;  // 指针域,指向下一个节点
} LNode, *LinkList;      // 别名:LNode 表示节点,LinkList 表示链表头指针

2. 初始化链表

初始化一个空链表,创建头节点并置空指针域。

bool InitList(LinkList &L) {
    L = (LNode*)malloc(sizeof(LNode));  // 分配头节点内存
    L->next = NULL;                     // 头节点的指针域置空
    return true;
}

3. 求链表长度

遍历链表,统计节点数量(不包含头节点)。

int length(LinkList L) {
    int len = 0;
    LNode *p = L;
    while (p->next != NULL) {  // 从头节点开始遍历
        p = p->next;
        len++;
    }
    return len;
}

4. 按序号查找节点

找到链表中第 i 个位置的节点(头节点序号为0)。

LNode *GetElem(LinkList L, int i) {
    LNode *p = L;
    int j = 0;
    while (p != NULL && j < i) {  // 遍历直到第 i 个节点
        p = p->next;
        j++;
    }
    return p;  // 返回节点指针,若未找到返回 NULL
}

5. 按值查找节点

找到链表中第一个值为 e 的节点。

LNode *LocateElem(LinkList L, int e) {
    LNode *p = L->next;  // 从第一个实际节点开始查找
    while (p != NULL && p->data != e) {
        p = p->next;
    }
    return p;  // 返回节点指针,若未找到返回 NULL
}

6. 插入节点

在链表的第 i 个位置插入新节点。

bool ListInsert(LinkList &L, int i, int e) {
    LNode *p = L;
    int j = 0;
    while (p != NULL && j < i - 1) {  // 找到第 i-1 个节点
        p = p->next;
        j++;
    }
    if (p == NULL) return false;  // 位置不合法

    LNode *s = (LNode*)malloc(sizeof(LNode));  // 创建新节点
    s->data = e;
    s->next = p->next;  // 新节点指向原第 i 个节点
    p->next = s;        // 原第 i-1 个节点指向新节点
    return true;
}

7. 删除节点

删除链表中第 i 个节点,并保存其值到 e

bool ListDelete(LinkList &L, int i, int &e) {  // 注意 e 应为引用类型
    LNode *p = L;
    int j = 0;
    while (p != NULL && j < i - 1) {  // 找到第 i-1 个节点
        p = p->next;
        j++;
    }
    if (p == NULL || p->next == NULL) return false;

    LNode *q = p->next;  // q 指向待删除节点
    e = q->data;          // 保存被删除节点的值
    p->next = q->next;    // 绕过 q 节点
    free(q);              // 释放内存
    return true;
}

8. 头插法构建链表

从链表头部依次插入节点,输入 9999 结束。


LinkList List_HeadInsert(LinkList &L) {
    LNode *s;
    int x;
    L = (LNode*)malloc(sizeof(LNode));  // 创建头节点
    L->next = NULL;
    scanf("%d", &x);  // 输入第一个值

    while (x != 9999) {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;  // 新节点指向原第一个节点
        L->next = s;        // 头节点指向新节点
        scanf("%d", &x);    // 继续输入
    }
    return L;
}

9. 尾插法构建链表

从链表尾部依次插入节点,输入 9999 结束。

LinkList List_TailInsert(LinkList &L) {
    int x;
    L = (LNode*)malloc(sizeof(LNode));  // 创建头节点
    LNode *s, *r = L;                  // r 始终指向尾节点
    scanf("%d", &x);

    while (x != 9999) {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;    // 尾节点的 next 指向新节点
        r = s;          // r 更新为新尾节点
        scanf("%d", &x);
    }
    r->next = NULL;     // 尾节点指针置空
    return L;
}

10. 完整代码与总结

以下是完整的单链表实现代码:

#include<stdio.h>
#include <cstdlib> 


typedef struct LNode {
    int data;
    struct LNode *next;
} LNode, *LinkList;

// 此处插入上述所有函数实现

int main() {
    LinkList L;
    InitList(L);  // 初始化链表

    // 示例:尾插法插入数据 1, 2, 3
    List_TailInsert(L);  // 输入 1 2 3 9999

    // 插入节点到第2个位置(值为10)
    ListInsert(L, 2, 10);

    // 删除第3个节点
    int deletedValue;
    ListDelete(L, 3, deletedValue);
    cout << "Deleted value: " << deletedValue << endl;

    return 0;
}

总结

  • 单链表的优势

    • 动态内存分配,无需预先知道数据规模。

    • 插入和删除操作的时间复杂度为 O(1)(找到位置后)。

  • 注意事项

    • 操作时需正确处理指针的指向关系。

    • 避免内存泄漏(每次 malloc 后需 free)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xienda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值