旭说数据结构之链表补充(双向链表)

上文已经介绍了链表中的单链表,这里我们再叙述一下双向链表

1.双向链表

对比单链表,双向链表能够直接找到节点的前驱,也就能从任意一个节点到达链表的头结点和尾节点。如下图所示:
这里写图片描述
下面我们还是从使用的角度出发来定义双向链表的接口。我想使用一个双向链表,那我就new一个来用。然后我就往里插入元素。之后我又想在某个索引处插入一个元素。于是我就可以写出下面的代码:

    TwoDirectionsLinkList<int> * twoDirectionsLinkList = new TwoDirectionsLinkList<int>();//new一个双链表对象来用
    twoDirectionsLinkList->insertElementToEnd(1);//在尾端插入
    twoDirectionsLinkList->insertElementToEnd(3);
    twoDirectionsLinkList->insertElementToEnd(4);
    twoDirectionsLinkList->insertElementToEnd(5);//此时链表中为1345
    twoDirectionsLinkList->printAllElement();
    twoDirectionsLinkList->insertElementToIndex(2,2);//在索引2处插入,此时链表中为12345
    twoDirectionsLinkList->printAllElement();
    twoDirectionsLinkList->deleteElementAtIndex(3);//删除索引3处的节点,此时链表中为1245
    twoDirectionsLinkList->printAllElement();

接下来就是来实现这些接口里的具体内容。
我们要使用双向链表,就要定义一个双向链表的类,姑且叫做TwoDirectionsLinkList,为了扩展性我们使用模板。类TwoDirectionsLinkList中应该有成员变量

TwoDirectionsLinkNode<DataType>* _head;
int _length;

其中TwoDirectionsLinkNode<DataType>* _head;为头结点,int _length;记录链表的长度。节点类TwoDirectionsLinkNode我们也需要定义,节点类中应该有三个成员变量:

    DataType _data;//存储数据
    TwoDirectionsLinkNode<DataType>* _next;//指向后继节点
    TwoDirectionsLinkNode<DataType>* _prior;//指向前驱节点

new一个双向链表时,调用TwoDirectionsLinkList的构造函数,这样就有了头节点了,我们就可以在头节点的基础上进行操作了。

    TwoDirectionsLinkList()
    {
        //头结点我随便放个数据0
        _head = new TwoDirectionsLinkNode<DataType>(0);
        _length = 0;
    }

插入新节点的操作,如下图所示,首先我们把指针p移动到要插入索引的前一个索引处,然后让新节点的_next指针指向p的_next(也就是索引处的节点),然后让p的_next指向新节点,然后让新节点的_prior指向p,再让索引处节点的_prior指向新节点。
这里写图片描述

bool insertElementToIndex(int index,DataType data)//插入到链表的指定位置处
    {
        if (_length == 0)
        {//在长度为0的情况下,可以插入到索引1处
            if (index == 1)
            {
                //链表长度为0,即只有头节点时,把新节点插入
                TwoDirectionsLinkNode<DataType>* newNode 
                = new TwoDirectionsLinkNode<DataType>(data);
                _head->_next = newNode;
                newNode->_prior = _head;
                _length++;
                return true;
            }else
            {
                return false;
            }
        }
        //长度不为0的情况下,只能在1~_length范围内插入
        if (index <=0 || index > _length)return false;
        TwoDirectionsLinkNode<DataType>* p = _head;

        //把指针p指向指定索引前的那个节点
        for (int i = 0;i<index -1 ;i++)
        {
            p=p->_next;
        }
        TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
        if (newNode == NULL)return false;
        newNode->_next = p->_next;
        p->_next = newNode;
        newNode->_prior = p;
        newNode->_next->_prior = newNode;
        _length++;
        return true;
    }

这样我们就解决双向链表的插入与删除问题,下面是双向链表的.h文件,

template<typename DataType>class TwoDirectionsLinkList;


template<typename DataType>class TwoDirectionsLinkNode
{

public:
    TwoDirectionsLinkNode(DataType data):_next(NULL),_prior(NULL),_data(data)
    {

    }

private:
    DataType _data;//存储数据
    TwoDirectionsLinkNode<DataType>* _next;//指向后继节点
    TwoDirectionsLinkNode<DataType>* _prior;//指向前驱节点
    friend class TwoDirectionsLinkList<DataType>;

};

template<typename DataType>class TwoDirectionsLinkList
{
public:
    TwoDirectionsLinkList()
    {
        //头结点我随便放个数据0
        _head = new TwoDirectionsLinkNode<DataType>(0);
        _length = 0;
    }


    //双向链表的操作
    bool insertElementToEnd(DataType data)//插入到链表的尾部,如果成功,返回true
    {
        TwoDirectionsLinkNode<DataType>* p = _head;
        while(p->_next){//把p指针指向链表的尾部
            p=p->_next;
        }
        //在尾部插入新节点
        TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
        p->_next = newNode;
        newNode->_prior = p;
        _length++;
        return true;
    }
    bool insertElementToIndex(int index,DataType data)//插入到链表的指定位置处
    {
        if (_length == 0)
        {//在长度为0的情况下,可以插入到索引1处
            if (index == 1)
            {
                //链表长度为0,即只有头节点时,把新节点插入
                TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
                _head->_next = newNode;
                newNode->_prior = _head;
                _length++;
                return true;
            }else
            {
                return false;
            }
        }
        //长度不为0的情况下,只能在1~_length范围内插入
        if (index <=0 || index > _length)return false;
        TwoDirectionsLinkNode<DataType>* p = _head;

        //把指针p指向指定索引前的那个节点
        for (int i = 0;i<index -1 ;i++)
        {
            p=p->_next;
        }
        TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
        if (newNode == NULL)return false;
        newNode->_next = p->_next;
        p->_next = newNode;
        newNode->_prior = p;
        newNode->_next->_prior = newNode;
        _length++;
        return true;
    }
    bool deleteElementAtIndex(int index)//删除指定位置的元素,如果成功,返回true
    {
        if (_length == 0)return false;
        if (index <= 0 || index>_length)return false;
        TwoDirectionsLinkNode<DataType>* p = _head;
        //把指针p指向指定索引前的那个节点
        for (int i = 0;i<index -1 ;i++)
        {
            p=p->_next;
        }
        TwoDirectionsLinkNode<DataType>* temp = p->_next;
        p->_next = p->_next->_next;
        p->_next->_prior = p;
        delete temp;        
        return true;
    }

    int getLength()//获取链表的长度
    {
        return _length;
    }
    void printAllElement()//打印表中的元素
    {
        cout<<"打印元素"<<endl;
        TwoDirectionsLinkNode<DataType>* p = _head;
        while(p->_next)
        {
            p=p->_next;
            cout<<p->_data<<endl;
        }
    }

private:
    TwoDirectionsLinkNode<DataType>* _head;
    int _length;
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值