数据结构与算法学习笔记之线性表三---单链表的表示和实现(C++)

目录

前言

一、顺序表的优缺点

二、单链表的表示和实现

1.初始化

2.清空表

3.销毁

4.表长

5.表空

6.获取表中的元素

7.下标

8.直接前驱

9.直接后继

10.插入

11.删除

12.遍历链表

13.测试代码


前言

这篇博客主要介绍单链表的表示和实现。

一、顺序表的优缺点

线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单直观的公式来表示。当然这种存储结构也存在弱点:在作插入或删除操作时,需移动大量元素。

二、单链表的表示和实现

单链表的两个要素:数据域,指针域。其中数据域表示的是当前结点的数据,指针域指向的下一个结点的地址。

单链表的定义如下:

cpp 复制代码
// - - - - - 线性表的单链表存储结构 - - - - -
typedef int ElemType;
typedef int Staus;
typedef struct LNode {
    ElemType data;          // 数据域
    struct LNode *next;     // 指针域
} LNode, *LinkList;

1.初始化

cpp 复制代码
// 链表初始化
Staus initLinkList(LinkList &linkList) {
    linkList = new LNode;   // 创建头结点
    if (!linkList) {        // 内存分配失败
        return false;
    }
    linkList->next = nullptr; // 头结点的指针域置空
    return true;
}

2.清空表

遍历单链表,置空指针

cpp 复制代码
// 清空链表
void clearLinkList(LinkList &linkList) {
    LinkList p, q;
    p = linkList->next;
    while (p) {
        q = p;
        p = p->next;
        delete q;
    }
    linkList->next = nullptr;
}

3.销毁

cpp 复制代码
// 销毁链表
void destroyLinkList(LinkList &linkList) {
    clearLinkList(linkList);
    delete linkList;
    linkList = nullptr;
}

4.表长

cpp 复制代码
// 表长
int linkListLength(LinkList &link){
    LNode * p =  link->next;
    int len = 0;
    while (p) {
        p = p->next;
        len++;
    }
    return len;
}

5.表空

cpp 复制代码
// 表空
Status linkListEmpty(LinkList &link){
    return linkListLength(link) == 0;
}

6.获取表中的元素

cpp 复制代码
// 获取表中的元素
Status getElemLinkList(LinkList &link,int pos,ElemType * element){
    if (pos < 1|| pos > linkListLength(link)) {
        return 0;
    }
    LinkList p = link->next;
    int j = 1;
    while (p && j < pos) {
        p = p ->next;
        ++j;
    }
    if (!p ||j > pos) {
        return 0;
    }
    *element = p->data;
    return 1;
}

7.下标

cpp 复制代码
// 获取数据元素element下标
Status getLocateinkList(LinkList &link,ElemType element,int * location){
    LinkList p = link->next;
    int j = 1;
    while (p) {
        if (p->data == element) {
            * location = j;
            return 1;
        }
        p = p ->next;
        ++j;
    }
    return 0;
}

8.直接前驱

cpp 复制代码
// 直接前驱
Status priorElemLinkList(LinkList &link,ElemType current,ElemType * priorElement){
    LinkList p = link->next;
    LinkList head = link;
    int j = 1;
    while (p) {
        if (p->data == current) {//找到数据元素
            if (j > 1) {
                * priorElement = head->data;
                return 1;
            }
        }
        p = p ->next;
        head = head->next;
        ++j;
    }
    return 0;
}

9.直接后继

cpp 复制代码
// 直接后继
Status nextElemLinkList(LinkList &link,ElemType current,ElemType * nextElement){
    LinkList p = link->next;
    while (p) {
        if (p->data == current) {//找到数据元素
            if (p -> next != nullptr) {
                * nextElement = p->next->data;
                return 1;
            }
        }
    }
    return 0;
}

10.插入

cpp 复制代码
// 单链表插入
Status insertLinkList(LinkList &head, int pos, int element) {
    if (pos < 1) {      // 位置非法
        return 0;
    }
    LinkList p = head;
    int j = 0;
    while (p && j < pos - 1) {
        p = p->next;
        ++j;
    }
    if (!p || j > pos - 1) {
        return 0;
    }

    LinkList q = new LNode; // 生成新节点
    if (!q) {               // 内存分配失败
        return 0;
    }
    q->data = element;
    q->next = p->next;
    p->next = q;
    return 1;
}

11.删除

cpp 复制代码
// 单链表删除
Status deleteLinkList(LinkList &head, int pos) {
    if (pos < 1 || !head->next) {  // 位置非法或空链表
        return false;
    }
    LinkList p = head;
    int j = 0;
    while (p->next && j < pos - 1) { // 找到要删除结点的前一个结点
        p = p->next;
        ++j;
    }
    if (!p->next || j > pos - 1) {   // 删除位置超出范围
        return false;
    }
    LinkList q = p->next;   // 要删除的结点
    p->next = q->next;      // 前一个结点指向后一个结点
    delete q;               // 释放删除结点的内存
    return true;
}

12.遍历链表

cpp 复制代码
// 遍历链表
void traverseList(LinkList linkList) {
    LinkList p = linkList->next;
    while (p) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

13.测试代码

cpp 复制代码
void testLinkList(void){
    LinkList myList;
    if (!initLinkList(myList)) {
        cout << "链表初始化失败!" << endl;
    }
    cout<<"表长:"<<linkListLength(myList)<<endl;
    int values[] = {1, 2, 3, 4, 5};
    int size = sizeof(values) / sizeof(values[0]);
    if (!createLinkList(myList, values, size)) {
        cout << "创建链表失败!" << endl;
        destroyLinkList(myList); // 避免内存泄漏
    }

    cout << "链表元素:";
    traverseList(myList);
    cout<<"表长:"<<linkListLength(myList)<<endl;
    
    cout << "获取某个位置的数据元素"<<endl;
    for (int i = -1; i <= 6; i++) {
        int element;
        if (getElemLinkList(myList, i, &element)) {
            cout<<"第"<<i<<"个数据元素获取成功,数据元素为:"<<element<<"\t"<<endl;
        }else{
            cout<<"第"<<i<<"个数据元素获取失败!"<<endl;
        }
    }
    cout<<endl;
    cout << "获取单链表数据元素下标"<<endl;
    for (int i = -1; i <= 6; i++) {
        int locate;
        if (getLocateinkList(myList, i, &locate)) {
            cout<<"数据元素"<<i<<"下标获取成功,下标为:"<<locate<<"\t"<<endl;
        }else{
            cout<<"数据元素"<<i<<"下标获取失败!"<<endl;
        }
    }
    cout<<endl;
    cout << "获取单链表数据元素直接前驱"<<endl;
    for (int i = -1; i <= 6; i++) {
        int element;
        if (priorElemLinkList(myList, i, &element)) {
            cout<<"数据元素"<<i<<"直接前驱为:"<<element<<"\t"<<endl;
        }else{
            cout<<"数据元素"<<i<<"没有直接前驱!"<<endl;
        }
    }

    // 插入元素
    int insertPos = 3;
    int insertElement = 10;
    if (!insertLinkList(myList, insertPos, insertElement)) {
        cout << "插入元素失败!" << endl;
        destroyLinkList(myList); // 避免内存泄漏
    }

    cout << "插入后的链表元素:";
    traverseList(myList);

    // 删除元素
    int deletePos = 2;
    if (!deleteLinkList(myList, deletePos)) {
        cout << "删除元素失败!" << endl;
        destroyLinkList(myList); // 避免内存泄漏
    }

    cout << "删除后的链表元素:";
    traverseList(myList);

    // 清空链表
    clearLinkList(myList);
    cout << "链表已清空!" << endl;

    // 销毁链表
    destroyLinkList(myList);
    cout << "链表已销毁!" << endl;
}
相关推荐
jimmy.hua5 分钟前
C++刷怪笼(5)内存管理
开发语言·数据结构·c++
神之王楠8 分钟前
学习风格的类型
学习
xiaobai12 38 分钟前
二叉树的遍历【C++】
开发语言·c++·算法
DieSnowK15 分钟前
[项目][WebServer][Makefile & Shell]详细讲解
开发语言·c++·http·makefile·shell·项目·webserver
Freak嵌入式16 分钟前
全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类
java·开发语言·数据结构·python·接口·抽象基类
paixiaoxin19 分钟前
学术新手进阶:Zotero插件全解锁,打造你的高效研究体验
人工智能·经验分享·笔记·机器学习·学习方法·zotero
知识分享小能手21 分钟前
mysql学习教程,从入门到精通,SQL 删除数据(DELETE 语句)(19)
大数据·开发语言·数据库·sql·学习·mysql·数据开发
晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑1 小时前
苍穹外卖学习笔记(五)
java·笔记·学习
MogulNemenis1 小时前
力扣春招100题——队列
数据结构·算法·leetcode
dc爱傲雪和技术1 小时前
在 VS Code 中调试 C++ 项目
开发语言·c++