【C++实现单链表】

本文介绍了数组和单链表两种数据结构,强调了它们在内存存储、访问速度和操作效率上的差异。数组提供随机访问,但插入删除操作复杂;单链表插入删除高效,但访问需遍历。并提供了C++实现单链表插入和删除的示例代码。
摘要由CSDN通过智能技术生成
概要:本期主要讲解数组和单链表的结构、它们之间的区别以及单链表的操作实现。

一、什么是数组?

数组是一组地址空间相连 的内存单元组成的有限序列。
如下图所示:

在这里插入图片描述
上面展示的是一个长度为4的int型数组Array,数组的下标从0开始

数组由于在内存中是连续的地址存储,支持随机访问,可以通过数组下标访问元素,时间复杂度的是O(1),但若是对数组进行插入、删除操作,其平均时间复杂度是O(n),原因是对数组元素进行插入或者删除操作时,该元素的后面元素都需要进行后移或者前移的操作。

二、什么是单链表?

链表是一组 任意的 内存单元组成的有序序列。
如下图所示:
在这里插入图片描述
上面展示的是单链表的结构。

一个存储单元分为指针域和数据域,顾名思义,指针域存储的是单元在内存中的地址,数据域存储的是数据元素。因此链表相对于数组会更消耗内存空间
由于链表在内存中的分布是离散的,每次访问某个数据只能通过前一个元素来找后一个元素,所以,链表的查询、遍历的平均时间复杂是O(n),但是若进行链表的插入、删除操作,其平均时间复杂度为O(1),原因是对链表进行删除节点操作,只需要将其的前一节点的指针指向其后一节点。而实现链表的插入节点操作,只需要将该节点的指针指向添加节点的数据域,再将添加节点的指针指向原先节点的后一节点的数据域

单链表的节点删除如下图所示:
在这里插入图片描述
单链表的节点插入如下图所示:
在这里插入图片描述

三、附上单链表的操作C++实现:

0.单链表结构和初始化

创建一个单链表类LinkedList,再声明一个链表节点类作为其成员变量。

//结构
class LinkedList
{
private:
    class Node
    {
    public:
        Node *next;
        QString data;
    };

    Node *head;

    int length = 0;
public:
    LinkedList();
};
LinkedList::LinkedList()
{
    head = new Node;
    head->data = "";
    head->next = nullptr;
    length = 0;
}

1.创建单链表

尾插法

//尾插法创建n个节点的链表(顺序)
void LinkedList::TailCreateLinkedList(int n)
{
    Node *pre = head;
    length = n;
    int i = 0;
    while (i < n) {
        qDebug()<< QStringLiteral("请输入第") << i << QStringLiteral("个结点的数据:");
        Node *cur = new Node;
        string str;
        cin >> str;
        cur->data = QString::fromStdString(str);
        ++i;
        pre->next = cur;
        pre = cur;
        cur->next = nullptr;
    }
}

头插法

//头插法创建n个节点的链表(逆序)
void LinkedList::HeadCreateLinkedList(int n)
{
    Node *pre = head;
    length = n;
    int i = 0;
    while (i < n) {
        qDebug()<< QStringLiteral("请输入第") << i << QStringLiteral("个结点的数据:");
        Node *cur = new Node;
        string str;
        cin >> str;
        cur->data = QString::fromStdString(str);
        ++i;
        cur->next = pre->next;
        pre->next = cur;
    }
}
2.打印单链表
//打印链表内容
void LinkedList::DisplayLinkedList()
{
    if(length == 0)
    {
        qDebug()<<QStringLiteral("链表为空!")<<endl;
        return ;
    }
    Node *_node = head->next;//节点1
    int i = 0;
    while(_node)
    {
        qDebug()<<QStringLiteral("第")<<i++<<QStringLiteral("个节点的数据:")<<_node->data<<endl;
        if(_node->next == nullptr)
        {
            return ;
        }
        _node = _node->next;
    }
}
3.查询节点位置
//查询节点位置
int LinkedList::GetNodeIndex(QString data)
{
    if(length == 0)
    {
        qDebug()<<QStringLiteral("链表为空!")<<endl;
        return -1;
    }
    Node *_node = head->next;//节点1
    int i = 0;
    while(_node)
    {
        if(_node->data == data)
        {
            qDebug()<<QStringLiteral("节点位置为:")<< i <<endl;
            return i;
        }
        if(_node->next == nullptr)
        {
            qDebug()<<QStringLiteral("节点不存在!")<<endl;
            return -1;
        }
        _node = _node->next;
        i++;
    }
}
4.插入节点到指定位置
//在指定位置后插入节点(前插可以参照后插实现)
void LinkedList::BackInsertNodeToLinkedList(int index,QString data)
{
    if(index < 0 || index >=length)
    {
        qDebug()<<QStringLiteral("输入位置有误!")<<endl;
        return ;
    }
    Node *_node = new Node;
    if(length == 0)
    {
        _node = head;
    }
    else
    {
        _node = head->next;
    }
    int i = 0;
    while(_node)
    {
        if(i == index)
        {
            Node* _nextNode = _node->next;//记录未插入是index位置的下一节点
            Node *_newNode = new Node;//创建新节点
            _newNode->data = data;
            _node->next = _newNode;
            _newNode->next = _nextNode;
            qDebug()<<QStringLiteral("节点插入成功!")<<endl;
            length++;
            return ;
        }
        if(_node->next == nullptr)
        {
            qDebug()<<QStringLiteral("节点插入失败!")<<endl;
            return ;
        }
        _node = _node->next;
        i++;
    }

}
5.删除单链表指定节点
//删除指定位置节点
void LinkedList::DeleteNodeInLinkedList(int index)
{
    if(index < 0 || index >=length)
    {
        qDebug()<<QStringLiteral("输入位置有误!")<<endl;
        return ;
    }
    Node *_node = new Node;
    if(length == 0)
    {
        _node = head;
    }
    else
    {
        _node = head->next;
    }
    int i = 0;
    while(_node)
    {
        if(i == index-1)//当前为index位置前一节点
        {
            Node* _delNode = _node->next;
            Node* _nextNextNode = _node->next->next;//记录index位置的下一节点
            _node->next = _nextNextNode;
            delete _delNode;
            _delNode = NULL;
            length--;
            qDebug()<<QStringLiteral("节点删除成功!")<<endl;
            return ;
        }
        if(_node->next == nullptr)
        {
            qDebug()<<QStringLiteral("节点删除失败!")<<endl;
            return ;
        }
        _node = _node->next;
        i++;
    }
}
6.获取单链表长度
//获取链表长度
int LinkedList::GetLinkedListLength()
{
    Node *_node = head->next;
    int i = 0;
    while(_node)
    {
        i++;
        _node = _node->next;
    }
    length = i;
    qDebug()<<QStringLiteral("链表长度为:")<< length <<endl;
    return length;
}

结尾:本期线性表的讲解就到这里结束啦,下期继续学习循环单链表和双链表的相关知识:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

葛狂的博客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值