【C++】 双向链表.cpp

来源:互联网 发布:泊松过程 知乎 编辑:程序博客网 时间:2024/05/04 02:57

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。


一般我们都构造双向循环链表,因为双向链表解决了单向链表的不足和问题,而单链表因为出现的问题多,所以在面试中经常会考到单链表的问题。


在这里,我用  .cpp对双向链表的基本操作进行实现。


具体代码如下:

  List.h文件:

#pragma once typedef int DataType; struct ListNode  //全部用作公有的就定义为struct,用作私有就定义class{                 //当然用class,写在public中也可以    DataType _data;    ListNode* _next; //前驱指针    ListNode* _prev; //后继指针     ListNode(DataType x) //构造函数        :_data(x)        ,_next(NULL)        ,_prev(NULL)    {} }; class List{public:    List()        :_head(NULL)        ,_tail(NULL)    {}     ~List()    {        Clear();    } public:    void PushBack(DataType x)    {        if(_head == NULL)        {            _head = _tail = new ListNode(x);//调用构造函数        }        else        {            ListNode* tmp = new ListNode(x);            _tail->_next = tmp;            tmp->_prev = _tail;             _tail = tmp;         }    }     void PopBack()    {        //没有节点        //一个节点        //一个以上节点        if(_head == NULL)        {            return;        }        else if(_head == _tail)        {            delete _head;            _head = _tail = NULL;        }        else        {            ListNode* cur = _tail->_prev;            delete _tail;            _tail = cur;            cur->_next = NULL;        }    }     void PushFront(DataType x)    {        if(_head == NULL)        {            _head = _tail = new ListNode(x);        }        else        {            ListNode* tmp = new ListNode(x);            tmp->_next = _head;            _head = tmp;        }    }     void PopFront()    {        if(_head == NULL)//空        {            return;        }        else if(_head == _tail)//一个节点        {            delete _head;            _head = _tail = NULL;        }        else        //一个以上节点        {            ListNode* del = _head;            _head = _head->_next;            _head->_prev = NULL;            delete del;        }    }     void Insert(ListNode* pos,DataType x)    {        assert(pos);         if(pos == _tail)        {            PushBack(x);        }        else        {            /*            ListNode* tmp = new ListNode(x);            tmp->_next = pos->_next;            pos->_next->_prev = tmp;  //使用这种两个指针的方式虽然可以达到目的,但是容易出现问题                                                  pos->_next = tmp;         //首先得考虑pos是否为空,其次若pos->_next为空,再想找到它的prev就会出错            tmp->_prev = pos;            */             ListNode* tmp = new ListNode(x);//这样定义两个指针保存前后的节点,就不容易出错            ListNode* next = pos->_next;            tmp->_next = next;            next->_prev = tmp;            pos->_next = tmp;            tmp->_prev = pos;         }    }     ListNode* Find(DataType x)    {        if(_head == NULL)        {            return NULL;//找不到返回空        }        else        {            ListNode* cur = _head;            while(cur)            {                if(cur->_data == x)                {                    return cur;                }                cur = cur->_next;            }        }     }     void Erase(ListNode* pos)    {        assert(_head);        assert(pos);         if(pos == _head)//删除头节点        {            PopFront();            /*            ListNode* del = _head;            _head = _head->_next;            _head->_prev = NULL;            delete del;            */        }        else if(pos == _tail)//删除尾节点        {            PopBack();        }        else // 删除非头尾节点        {            /*            ListNode* cur = pos->_prev;            cur->_next = pos->_next;            pos->_next->_prev = cur;            delete pos;            */                        ListNode* prev = pos->_prev;            ListNode* next = pos->_next;            prev->_next = next;            next->_prev = prev;            delete pos;          }    }     void PrintList()//在此用不上前驱节点prev    {        ListNode* cur = _head;        while(cur)        {            cout<<cur->_data<<"->";            cur = cur->_next;        }        cout<<"NULL"<<endl;    }     void Clear()    {        ListNode* cur = _head;        while(cur)        {            ListNode* del = cur;            cur = cur->_next;            delete del;        }    }         //翻转双向链表    void reverse()    {        /*  ①.交换值        ListNode* begin = _head;        ListNode* end = _tail;         while(begin != end && begin->_prev != end)//当两个指针相遇或者已经偏离停止        {            swap(begin->_data , end->_data);            begin = begin->_next;            end = end ->_prev;        }        */         //②.交换指针        ListNode* cur = _head;                 while(cur)        {            swap(cur->_prev , cur->_next);//把每个节点的前后指针交换            cur = cur->_prev;        }        swap(_head,_tail);    } private:    ListNode* _head;    ListNode* _tail; }; void Test(){    List l;    l.PushBack(1);    l.PushBack(2);    l.PushBack(3);    l.PushBack(4);    l.PushBack(5);    l.PrintList();     l.PopBack();    l.PrintList();         l.PushFront(0);    l.PrintList();     l.PopFront();    l.PrintList();     l.Insert(l.Find(1),0);    l.PrintList();     l.Erase(l.Find(1));    l.PrintList();     l.reverse();    l.PrintList();}

List.cpp 文件:(测试)

#include<iostream>#include<assert.h>using namespace std;#include "DoubleSList.h"  //双向链表int main(){    Test();    return 0;}

我们发现,当遇到问题时不能直接上手去写,为什么?因为我们写的是代码,而不是bug,正确的程序是需要严谨的逻辑为前提,所以在写代码之前需要谨慎的思考各种临界的情况和异常,这是非常之重要的!

本文出自 “Vs吕小布” 博客,谢绝转载!

0 0
原创粉丝点击