当前位置: 首页 > article >正文

考研408-数据结构完整代码 线性表的链式存储结构 - 单链表

单链表操作详解(C++实现)

目录

  1. 单链表尾插法创建
  2. 单链表头插法创建
  3. 删除指定节点
  4. 按值查找
  5. 按序号查找
  6. 插入节点
  7. 完整代码示例
  8. 注意事项
  9. 总结

尾插法创建

#include<bits/stdc++.h>
using namespace std;

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

// 尾插法创建单链表
void List_TailInsert(LinkList& L) {
    L = (LNode*)malloc(sizeof(LNode));
    L->next = NULL;             // 创建头节点
    LNode* S, * r = L;          // r始终指向尾节点
    int X;
    cin >> X;
    while (X != 9999) {         // 输入9999时停止
        S = (LNode*)malloc(sizeof(LNode));
        r->next = S;            // 将新节点接在尾节点后
        r = S;                  // 更新尾节点指针
        S->next = NULL;         // 新节点的next置空
        S->data = X;            // 存入数据
        cin >> X;
    }
}

// 打印链表
void List_Print(LinkList L) {
    cout << "当前链表:" << endl;
    LNode* P = L->next;
    while (P != NULL) {
        cout << P->data << " ";
        P = P->next;
    }
    cout << endl;
}

int main() {
    LinkList L;
    List_TailInsert(L);
    List_Print(L);
    return 0;
}

代码说明
• 时间复杂度:O(n)
• 特点:新节点插入链表尾部,输入顺序与链表顺序一致
• 要点:维护尾指针r,每次插入后更新r


头插法创建

#include<bits/stdc++.h>
using namespace std;

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

// 头插法创建单链表
void List_HeadInsert(LinkList& L) {
    LNode* S; int X;
    L = (LNode*)malloc(sizeof(LNode));
    L->next = NULL;             // 创建头节点
    cin >> X;
    while (X != 9999) {         // 输入9999时停止
        S = (LNode*)malloc(sizeof(LNode));
        S->next = L->next;      // 新节点指向原首节点
        L->next = S;            // 头节点指向新节点
        S->data = X;            // 存入数据
        cin >> X;
    }
}

// 打印链表
void PrintList(LinkList L) {
    LNode* p = L->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

int main() {
    LinkList L = NULL;
    List_HeadInsert(L);
    PrintList(L);
    return 0;
}

代码说明
• 时间复杂度:O(n)
• 特点:新节点插入链表头部,输入顺序与链表顺序相反
• 要点:每次插入后修改头节点的next指针


删除指定节点

// 删除指定节点p(非尾节点)
bool DeleteNode(LNode* p) {
    if (p == NULL || p->next == NULL) // 空节点或尾节点无法删除
        return false;
    LNode* q = p->next;         // 获取后继节点
    p->data = q->data;          // 数据域替换
    p->next = q->next;          // 指针域跳过q
    free(q);                    // 释放内存
    return true;
}

代码说明
• 时间复杂度:O(1)
• 限制:无法删除最后一个节点
• 特点:通过复制后继节点数据实现伪删除


按值查找

// 按值查找并返回位置
LNode* LocateElem(LinkList L, int e, int& Locate) {
    LNode* P = L->next;
    Locate = 1;
    while (P != NULL && P->data != e) {
        P = P->next;
        Locate++;
    }
    if (P == NULL) Locate = -1; // 未找到标记-1
    return P;
}

/* 调用示例 */
int main() {
    // ...(初始化链表)
    int Locate = -1, e;
    cin >> e;
    LNode* K = LocateElem(L, e, Locate);
    if (K != NULL) {
        cout << "找到元素:" << K->data << " 位置:" << Locate;
    } else {
        cout << "元素未找到";
    }
}

按序号查找

// 按序号查找元素
bool List_LocateFind(LinkList L, int loc) {
    if (loc < 1) return false;
    LNode* p = L->next;
    int K = 1;
    while (p != NULL && K < loc) {
        p = p->next;
        ++K;
    }
    if (p == NULL) return false;
    cout << "位置" << loc << "的元素为:" << p->data;
    return true;
}

插入节点

// 带头节点的插入(位置从1开始)
bool List_Insert1(LinkList& L, int i, int e) {
    if (i < 1) return false;
    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;
    P->next = S;
    return true;
}

// 不带头节点的插入
bool List_Insert2(LinkList& L, int i, int e) {
    if (i < 1) return false;
    if (i == 1) { // 特殊处理第一个节点
        LNode* S = (LNode*)malloc(sizeof(LNode));
        S->data = e;
        S->next = L;
        L = S;
        return true;
    }
    // 其他位置与带头节点操作相同
    // ...(后续代码类似带头节点情况)
}

注意事项

  1. 内存管理:每次malloc后需对应free
  2. 边界处理:特别注意头节点和尾节点的操作
  3. 时间复杂度:
    • 查找操作:O(n)
    • 插入/删除:O(1)(已知前驱时)
  4. 输入约定:示例中使用9999作为终止输入标记

总结

操作时间复杂度要点
头插法O(n)维护头指针
尾插法O(n)维护尾指针
按值查找O(n)遍历比较
按序号查找O(n)计数器控制
节点插入O(n)找到前驱节点修改指针
节点删除O(1)需要前驱节点或特殊处理

单链表适合频繁插入删除的场景,但随机访问效率较低。理解指针操作是掌握链表的关键,建议通过画图辅助理解指针变化过程。


http://www.kler.cn/a/611970.html

相关文章:

  • 微商生态的技术重构:定制开发开源AI智能名片与S2B2C商城小程序源码的赋能逻辑
  • 登录接口带验证码自动化(tesseract-OCR)
  • Crypto Architecture Kit简介
  • DiskGenius 硬盘管理工具下载+D盘空间扩容给C盘教程
  • ZIP_STORED和ZIP_LZMA没有compresslevel参数!
  • Scala 简介
  • 数据库的DDL操作
  • Flutter视频播放优化
  • 【数学建模】(智能优化算法)元胞自动机在数学建模中的应用
  • LeetCode 20 Valid Parentheses 有效的括弧 Java
  • 5款视觉OCR开源模型
  • 输入百分比校验(数字非负数保留2位不四舍五入)
  • c# 动态库重名冲突处理方法 (起别名)
  • 面试记录3
  • 深度学习查漏补缺:3.从 Sigmoid 到 GELU
  • 使用Hash和HTML5的History API实现前端路由
  • IIR(无限冲激响应)滤波
  • 爬虫面试题
  • 大模型tokenizer重构流程
  • 【初探数据结构】直接插入排序与希尔排序详解