【数据结构(C++)】单链表

本文详细介绍了C++中单链表的数据结构,包括节点类、单链表类的定义和基本操作,如构造、判断空、获取长度、遍历、插入、删除和链接等。并通过学生结构体的实例演示了如何使用单链表来存储和操作数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      线性表包含 数据域和指针域 其中,data存储数据本身的值,next存储后继元素的地址 下面的图表示的是一个数据节点

单链表的结构示意图(包括空的单链表):

 

 

 

  1. 单链表的节点类:
    复制代码
    template<class T>
    class Node
    {
    public:
    T data;//数据
    Node<T> *next;//next指针
    Node()
    {
    this->next=NULL;//构造空的节点
    }
    Node(T data,Node<T> *next=NULL)//构造一个节点
    {
    this->data=data;
    this->next=next;
    }
    };
    复制代码
  2. 单链表类声明如下:
    复制代码
    #include<iostream>
    #include "Node.h" //单链表节点类
    template<class T>
    class SinglyLinkedList //单链表类
    {
    public:
    Node<T> *head;//单链表的头指针。
    SinglyLinkedList();//构造空的单链表。
    SinglyLinkedList(T value[], int n);//构造由指定的数组提供的单链表
    ~SinglyLinkedList();//析构
    bool isEmpty();//判断是否为空。
    int length();//获取长度
    Node<T>* getNode(int i);//返回第i(i>=0)个节点指针
    T get(int i);//返回第i个元素
    bool set(int i,T x);//设置第i个元素为x
    template<class T> friend std::ostream& operator<<(std::ostream& out,SinglyLinkedList<T> &list);
    Node<T>* insert(int i,T x);//插入第I个节点并返回第i个节点的指针
    bool remove(int i,T& old);//删除第i个元素,将删除的元素存放到old
    void clear();//清空单链表
    void concat(SinglyLinkedList<T> &list);//将List链接在当前单链表之后
    };
    复制代码
  3. 单链表部分如构造空的链表对象,析构,判断为空的实现,没有要讲的算法,实现如下:
    复制代码
    template<class T>
    SinglyLinkedList<T>::SinglyLinkedList()//构造空的单链表
    {
    this->head=NULL;
    }
    template<class T>
    SinglyLinkedList<T>::~SinglyLinkedList()//析构
    {
    clear();
    }
    template<class T>
    bool SinglyLinkedList<T>::isEmpty()//判断链表是否为空
    {
    return this->head==NULL;
    }
    复制代码
  4. 单链表的遍历操作,遍历单链表是指从第一个节点开始访问,沿着节点的Next可依次访问单链表中的各个节点,并且各个节点只被访问一次。实现的单链表遍历的基本算法如下:
    复制代码
    int j=0;
    Node<T> *p=head;
    while(p!=NULL&&j<i)
    {
    j++;
    p=p->next;
    }
    复制代码

    单链表的length(),get(),set(),clear()和输出等操作都基于以上算法。

    复制代码
    template<class T>
    int SinglyLinkedList<T>::length()
    {
    int i=0;
    Node<T> *p=head;//创建一个用于遍的变量
    while(p!=NULL)
    {
    i++;
    std::cout<<p->data;
    p=p->next;
    }
    return i;
    }
    template<class T>
    Node<T>* SinglyLinkedList<T>::getNode(int i)
    {
    if(i<0)
    return NULL;
    int j=0;
    Node<T> *p=head;
    while(p!=NULL&&j<i)
    {
    j++;
    p=p->next;
    }
    return p;
    }
    template<class T>
    T SinglyLinkedList<T>::get(int i)
    {
    Node<T> *p=getNode(i);
    if(p!=NULL)
    return p->data;
    T d;
    return d;
    //throw "单链表为空或者参数指定的元素不存在";
    }
    template<class T>
    bool SinglyLinkedList<T>::set(int i,T x)
    {
    Node<T> *p=getNode(i);
    if(p!=NULL)
    {
    p->data=x;
    return true;
    }
    return false;
    }
    template<class T>
    std::ostream& operator<<(std::ostream& out,SinglyLinkedList<T> &list)
    {
    Node<T> *p=list.head;
    out<<"(";
    while(p!=NULL)
    {
    out<<p->data;
    p=p->next;
    if(p!=NULL)
    out<<",";
    }
    out<<")\n";
    return out;
    }
    template<class T>
    void SinglyLinkedList<T>::clear()
    {
    Node<T> *p=head;
    while(p!=NULL)
    {
    Node<T> *q=p;
    p=p->next;
    delete q;
    }
    head=NULL;
    }
    复制代码

     

  5. 单链表的插入操作,单链表不像顺序表,对与表的插入和删除很简单:
    1. 空表插入/头插入
      Node<T> *q=NULL;
      if(head==NULL||i<0)//头插入(单链表为空或者)
      {
      q=new Node<T>(x,head);
      head=q;
      }
    2. 中间插入/尾插入
      p->next=new Node<T>(x,p->next);
    单链表insert()以及参数构造函数:
    复制代码
    template<class T>
    Node<T>* SinglyLinkedList<T>::insert(int i,T x)
    {
    Node<T> *q=NULL;
    if(head==NULL||i<0)//头插入(单链表为空或者)
    {
    q=new Node<T>(x,head);
    head=q;
    }
    else
    {
    int j=0;
    Node<T> *p=head;
    while(p->next!=NULL&&j<i-1)
    {
    j++;
    p=p->next;
    }
    q=new Node<T>(x,p->next);
    p->next=q;
    }
    return q;
    }

    template<class T>
    SinglyLinkedList<T>::SinglyLinkedList(T table[],int n)
    {
    head=NULL;
    if(n>0)
    {
    head=new Node<T>(table[0]);//创建节点
    Node<T> *rear=head;//创建一个指向头节点的指针
    int i=1;
    while(i<n)
    {
    rear->next=new Node<T>(table[i++]);
    rear=rear->next;
    }
    }
    }
    复制代码
  6. 单链表的删除操作也分两类:
    1. 头删除
      Node<T> *q=head;
      head=head->next;
      delete q;
    2. 中间/尾删除
      Node<T> *q=p->next;
      if(q!=NULL)//判断删除节点
      {
      p->next=q->next;//让删除节点的前驱Next指针下一节点
      delete q;//删除该节点
      }
    单链表的删除函数remove()实现:
    复制代码
    template<class T>
    bool SinglyLinkedList<T>::remove(int i,T &old)
    {
    if(i<0||head==NULL)
    {
    Node<T> *q=head;
    old=q->data;
    head=head->next;
    delete q;
    }
    else
    {
    Node<T> *p=getNode(i-1);//获取删除节点的前驱
    if(p!=NULL&&p->next!=NULL)//判断删除节点和删除节点是否为空
    {
    Node<T> *q=p->next;//新建一个节点指针,将删除接点复制过去
    old=q->data;
    p->next=q->next;//让删除节点的前驱Next指针下一节点
    delete q;//删除该节点
    return true;
    }
    }
    return false;
    }
    复制代码
  7. 单链表的链接函数:concat()
    复制代码
    template<class T>
    void SinglyLinkedList<T>::concat(SinglyLinkedList<T> &list)
    {
    if(this->head==NULL)
    {
    this->head=list->head;
    }
    else
    {
    Node<T> *p=head;
    while(p->next!=NULL)
    {
    p=p->next;
    }
    p=list->head;
    }
    list->head=NULL;//设置单链表为空,否则运行出错
    }
    复制代码

以上对C++单链表的分析 添加一个学生结构和一个测试函数:

Student.h

复制代码
struct Student
{
char number[10]; //学号
char name[20]; //姓名
double score; //得分
friend std::ostream& operator<<(std::ostream& out,Student &stu)
{
out<<"学号:"<<stu.number<<" 姓名:"<<stu.name<<" 得分:"<<stu.score;
return out;
}
};
复制代码

 主函数:

复制代码
#include<iostream>
#include "SinglyLinkedList.h"
#include "Student.h"
void _TestToSinglyLinkedList()
{
Student data[]={{"090313018","Silvester",45.4},{"090313018","捐赠",45.4},{"090313018","版主",45.6}};
SinglyLinkedList<Student> m(data,3);
Student t;
std::cout<<(m.isEmpty()?"不为空!":"该链表为空!")<<std::endl;
std::cout<<"长度:"<<m.length()<<std::endl;
std::cout<<"移除2个学生"<<m.remove(1,t)<<std::endl;
std::cout<<"t:"<<t<<std::endl;
std::cout<<"2个学生信息"<<m.getNode(1)<<std::endl;
Student s={"415646","fdsfs",453.1};
std::cout<<m.get(1)<<m.set(1,s)<<m.insert(5,s)<<std::endl;
}
void main()
{
_TestToSinglyLinkedList();
system("pause");
}
复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值