数据结构-01-链表数据结构之单链表

本文中的所有代码均在github上的项目中:List_DataStructure

一.链表:

1.1 链表的概念:

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分内容:一是存储数据元素的数据域,另一个是存储其他结点地址的指针域(不同种类的链表存储的结点地址不同)。

1.2 链表的种类:

链表根据每个结点存储的指向下一结点的链接不同而分为几类
单链表:结构最简单的链表,每个结点中都有指向下一结点的地址
双链表:对单链表做了部分加强,每个结点中都有两个地址,分别指向上一结点和下一结点
环形链表:尾结点中存储有头结点的地址,整个链表形成了一个封闭的环

二.单链表:

单链表又名单向链表,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取的方式,从头部开始遍历链表

2.1 单链表的基本结构:

单链表的开始是一个头指针,每个结点中都有指向下一结点的地址,尾结点中的地址为nullptr

这里写图片描述

单链表的C++实现:

1.首先创建单链表的结点类
template<typename Type> class SingleLinkedList;

template<typename Type>
class SingleLinkedListNode
{
private:
    //将链表类声明为友元
    friend typename SingleLinkedList<Type>;
    //构造函数和析构函数
    SingleLinkedListNode() :pnext(nullptr){}
    SingleLinkedListNode(const Type item, SingleLinkedListNode<Type> * next = nullptr) :data(item),pnext(next){}
    ~SingleLinkedListNode() {
        pnext = nullptr;
    }
public:
    //创建公共方法,用于获取结点中的数据
    Type GetData();SingleLinkedListNode<Type>&);
private:
    //结点类的私有属性,结点数据和下一结点的地址
    Type data;
    SingleLinkedListNode * pnext;
};
2.创建单链表类
#include"SingleLinkedListNode.h"

template <typename Type>
class SingleLinkedList
{
public:
    //构造函数和析构函数
    SingleLinkedList() :head(new SingleLinkedListNode<Type>()){}
    ~SingleLinkedList() {
        MakeEmpty();
        delete head;
    }
    //对单链表的基本操作
    void MakeEmpty();
    void Insert(Type item, int i = 0);
    void Remove(int i = 0);
    void RemoveAll(Type item);
    //返回单聊表的基本信息
    int length();
    Type Get(int i);
    //查找和排序
    SingleLinkedList<Type> * SequentialSearch(Type item);
    //基础功能
    void Print();
private:
    //链表的头节点是私有的
    SingleLinkedListNode<Type> *head;

};
3.创建一个单链表对象:
SingleLinkedList<int> list;

根据空参构造方法,创建单链表对象时初始化了一个私有的,没有数据的头结点*head

2.2 向单链表中插入数据:

单链表的一个可用的Insert( )方法版本:
该版本不用按照插入位置的不同(头尾体)而分情况实现,比较简洁

//向单链表中插入元素
template <typename Type>
void SingleLinkedList<Type>::Insert(Type item, int i = 0) {
    if (i < 0){
        cout << "请输入一个大于0的数" << endl;
    }
    SingleLinkedListNode<Type> *pmove = head;
    SingleLinkedListNode<Type> *pnode = new SingleLinkedListNode<Type>(item);
    //循环条件是j<i,且pmove的地址不能为空
    for (int j = 0; j < i&&pmove; j++){
        pmove = pmove->pnext;
    }
    //插入点越界
    if (pmove == nullptr){
        cout << "数据插入位置错误,单链表没那么长!" << endl;
    }
    pnode->pnext = pmove->pnext;
    pmove->pnext = pnode;
}

在中间部分插入数据

以中间部分插入为主讨论:

这里写图片描述

1,首先创建两个结点类型指针pmove 和pnode
2,将pmove指针移动到插入点,如上图,插入位置为a2,a3之间,pmove指向a2
3,变更结点中存储的地址以实现结点插入

pnode->pnext = pmove->pnext; //第一步
pmove->pnext = pnode; //第二步

第一步:待插入节点pnode的下一结点地址pnext指向a3,a3的地址为a2结点的下一结点地址pnext,也是pmove的pnext,即pmove->pnext
第二步:更改a2结点的下一结点地址pnext,使其指向待插入节点pnode

如上图所示,s为待插入节点pnode,p为插入点位置pmove

在头部插入数据

这里写图片描述

在尾部插入数据

这里写图片描述

测试单链表的插入方法:

int main() {
    SingleLinkedList<int> list;
    //向链表中插入20个数据
    for (int i = 0; i < 20; i++)
    {
        list.Insert(i*4,i);
    }
    //在链表头部插入数据
    list.Insert(10,0);
    //在链表尾部插入数据
    list.Insert(100,21);

    list.Print();
    cin.get();
    return 0;
}

执行结果:

这里写图片描述

2.3 删除单链表中的数据:

执行原理与添加数据相似,创建两个结点类型指针pdel和pmove
pdel指向待删除元素,pmove指向待删除结点的前一个结点

//删除单链表中的元素
template <typename Type>
void SingleLinkedList<Type>::Remove(int i = 0) {
    if (i < 0){
        cout << "请输入一个大于0的数" << endl;
    }
    SingleLinkedListNode<Type> *pmove = head, *pdel;
    for (int j = 0; j < i&&pmove->pnext; j++){
        pmove = pmove->pnext;
    }
    if (pmove->pnext == nullptr){
        cout << "删除出错,链表没有那么长!" << endl;
    }
    pdel = pmove->pnext;
    pmove->pnext = pdel->pnext;
    delete pdel;
}

2.3 单链表的其他方法:

2.3.1 销毁单链表

析构函数调用了此方法

//删除单链表
template <typename Type>
void SingleLinkedList<Type>::MakeEmpty() {
    SingleLinkedListNode<Type> *pdel;
    while (head->pnext != nullptr)
    {
        pdel = head->pnext;
        head->pnext = pdel->pnext;
        delete pdel;
    }
}

2.3.2 返回单链表长度

//返回单链表长度
template<typename Type>
int SingleLinkedList<Type>::length() {
    SingleLinkedListNode<Type> *pmove = head->pnext;
    int count = 0;
    while (pmove != nullptr) {
        pmove = pmove->pnext;
        count++;
    }
    return count;
}

2.3.3 打印单链表中的所有数据

//打印单链表中的所有数据
template<typename Type>
void SingleLinkedList<Type>::Print() {

    SingleLinkedListNode<Type> *pmove = head->pnext;
    cout << endl << "head";
    while (pmove != nullptr)
    {
        cout << "->" << pmove->data;
        pmove = pmove->pnext;
    }
    cout << "-over" << endl;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值