数据结构cpp实现——单链表

单链表

        采用链接存储方式的线性表称之为线性链表,最简单的线性链表结构为单链表。单链表的每一个元素用一个结点存储。data域用来存放数据,next域用来存放指向下一个元素的地址。

学习,编程,计算机,数据结构
            一般规定^表示指针指向空。利用单链表存储数据,在删减或增加元素时不需要移动元素,相比于顺序表,可以更高效地实现插入和删除操作。            对于不带头结点的单链表,在第i个节点前插入数据可以分为三种情况

            1)在i=1时,表示在单链表最前面插入元素,即原来第一个元素之前。

学习,编程,计算机,数据结构
            2)在1<i≤n时,新结点插入在原链表的a(i-1)和ai之间。
学习,编程,计算机,数据结构
            3)在i=n+1时,新节点插入在原链表表尾。

学习,编程,计算机,数据结构
            删除操作:相比于顺序表的移动前后元素,单链表的删除操作相当简单。删除当前结点后,把前一个结点的指针指向赋值为下一个即可。


学习,编程,计算机,数据结构
如果删除的结点为头结点,则需要修改头指针指向。            单链表的结点类模版定义和实现template<class T>

struct Node

{

    T data;//数据域

    Node<T> *next;//指针域


    Node(){next= nullptr;};//默认无参构造函数

    Node(T e,Node<T> *link= nullptr){data=e;next= link;};//有参构造函数

};            单链表的类模版定义和实现template<class T>

class LinkList {

private:

    Node<T> *head;//头结点指针

    int length;//元素个数长度

public:

    LinkList(){head= new Node<T>;length=0;};//无参构造器

    LinkList(T arr[],int n);//第一个参数为初始化数据的数组,第二个参数为对应的长度

    ~LinkList();//析构函数


    int GetLength() const{return length;};//返回单链表长度

    bool IsEmpty() const{return length==0;};//单链表是否为空

    void clear();//清空线性表

    void traverse() const;//遍历打印线性表

    int LocateElem(const T &e);//求e元素在线性表中的位置

    bool GetElem(int i, T &e) const;//获取第i个结点的数据赋值给e返回true,若失败则返回false

    bool SetElem(int i, const T &e);//修改第i个结点的值

    bool DeleteElem(int i, const T &e);//删除第i个结点,并将数据域返回给e

    bool insert(int i, const T &e);//在原链表的第i个结点之前插入e

    bool insert(const T&e);//在链表尾部插入结点

};


template<class T>

LinkList<T>::LinkList(T *arr, int n) {

    Node<T> *p;

    p=head=new Node<T>;

    assert(head);//头结点构造失败则终止程序

    for(int i=0;i<n;i++)

    {

        p->next=new Node<T>(arr[i], nullptr);

        assert(p->next);

        p=p->next;//逐级向下遍历

    }

    this->length=n;

}


template<class T>

LinkList<T>::~LinkList() {

    clear();

    delete head;

}


template<class T>

void LinkList<T>::clear() {

    Node<T> *p=head->next;

    while(p!= nullptr)

    {

        head->next=p->next;

        delete p;

        p=head->next;

    }

    length=0;

}


template<class T>

void LinkList<T>::traverse() const {

    Node<T> *p=head->next;

    while(p!= nullptr)

    {

        std::cout<<p->data<<" ";

        p=p->next;

    }

}


template<class T>

int LinkList<T>::LocateElem(const T &e) {

    Node<T> *p=head->next;

    int position=1;

    while(p!= nullptr)

    {

        if(p->data==e)

            return position;

        position++;

        p=p->next;

    }

    return 0;

}


template<class T>

bool LinkList<T>::GetElem(int i, T &e) const {

    if(i<1||i>length)

        return false;//元素取值位置非法

    else

    {

        Node<T> *p=head->next;

        for(int count=1;count<i;count++)

            p=p->next;

        e=p->data;

        return true;

    }

}


template<class T>

bool LinkList<T>::SetElem(int i, const T &e) {

    if(i<1||i>length)

        return false;

    else

    {

        Node<T> *p=head->next;

        for(int count=1;count<i;count++)

            p=p->next;

        p->data=e;

        return true;

    }

}


template<class T>

bool LinkList<T>::DeleteElem(int i, const T &e) {

    if(i<1||i>length)

        return false;

    else

    {

        Node<T> *p=head,*q;

        for(int count=1;count<i;count++)

            p=p->next;//p实际指到了要删除的元素的前一个结点

        e=p->next->data;//将第i个元素返回给e

        q=p->next;

        p->next=q->next;//将第i-1个节点的next指针指向下下个结点

        delete q;

        length--;

        return true;

    }

}


template<class T>

bool LinkList<T>::insert(int i, const T &e) {

    if(i<1||i>length+1)

        return false;

    else

    {

        Node<T> *p=head,*q;

        for(int count=1;count<i;count++)

            p=p->next;//定位到第i-1个结点

        q=new Node<T>(e, p->next);

        assert(q);

        p->next=q;

        length++;

        return true;

    }

}


template<class T>

bool LinkList<T>::insert(const T &e) {

    Node<T> *p,*q;

    q=new Node<T> (e, nullptr);

    for(p=head;p->next!= nullptr;p=p->next);

    p->next=q;//表尾指针指向新加入的结点q

    length++;

    return true;

}单链表相比于顺序表更加节省内存空间,并且在删除和插入操作方面,明显优于顺序表。缺点是不支持随机访问(像数组一样直接定位元素位置),必须通过头结点,依次遍历到所需要的结点。

发布评论
全部评论(16)
用户头像

无参构造函数更改bug。。。。head=new Node<T>

用户头像
Hewuhu#375861

@parth 行吧

用户头像

@Hewuhu_uu 我要开始搞下一个了,静态链表的

用户头像

@松前绪花 是啊,数据结构全是指针实现 [s-1]

用户头像
Hewuhu#375858

@parth 都补,都补(我就是个菜鸟……