数据结构与算法学习笔记之线性表三---单链表的表示和实现(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;
}
相关推荐
考试宝3 分钟前
国家宠物美容师职业技能等级评价(高级)理论考试题
经验分享·笔记·职场和发展·学习方法·业界资讯·宠物
霁月风1 小时前
设计模式——适配器模式
c++·适配器模式
ChoSeitaku2 小时前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表
偷心编程2 小时前
双向链表专题
数据结构
香菜大丸2 小时前
链表的归并排序
数据结构·算法·链表
jrrz08282 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
咖啡里的茶i2 小时前
Vehicle友元Date多态Sedan和Truck
c++
海绵波波1072 小时前
Webserver(4.9)本地套接字的通信
c++
黑叶白树2 小时前
简单的签到程序 python笔记
笔记·python
@小博的博客2 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习