模板(双向链表与队列)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板(双向链表与队列)相关的知识,希望对你有一定的参考价值。

       ”双向链表与队列“


          “双向链表”是包含两个指针域,一个数据域,既有指向前驱的指针,还有指向后继的指针,同时可以从两个方向对链表进行遍历,访问各个节点。“双向链表”较”单链表“在插入和删除节点方面更为简单,但是所占的空间比“单链表”大。“队列”的实现之所以选择使用双向链表,是因为队列的特点是“先进先出”,如若使用顺序表则很大程度上的浪费空间。在这样的情境下,链表较顺序表更为合适。


            根据“模板”的概念,设计并实现双向链表,进而实现队列的基本功能。下面是利用模板来实现双向链表的具体代码:


#pragma once
#include <assert.h>

//双向链表 
template <class T>
struct ListNode
{
     T _data;
     ListNode<T> * _next;
     ListNode<T> * _prev;
     ListNode(const T& x)
        :_data(x)
        , _next(NULL)
        , _prev(NULL)
     { }
};

template <class T>
class List
{
public:
    List()    //构造函数
       :_head(NULL)
       , _tail(NULL)
    { }
    
    ~List()   //析构函数
    {
        Clear();
    }
    
public:
    void pushBack(const T & x)     //尾插
    {
        if (_head == NULL)
        {
             _head = _tail = new ListNode<T>(x);
         }
        else
        {
            ListNode<T> * tmp = new ListNode<T>(x);
            _tail->_next = tmp;
            tmp->_prev = _tail;
            _tail = tmp;
            tmp->_next = NULL;
        }
    }
    
    void popBack()    //尾删
    {
        if (_head == NULL)
        {
            return;
        }
        else if (_head == _tail)
        {
            delete _tail;
            _head = _tail = NULL;
         }
        else
        {
            ListNode<T> * tmp = _tail->_prev;
            delete _tail;
            tmp->_next = NULL;
            _tail = tmp;
        }
    }
    
    void pushFront(const T & x)     //头插
    {
        ListNode<T> * tmp = new ListNode<T>(x);
        if (_head == NULL)
       {
           _head = _tail = tmp;
       }
        else
        {
            tmp->_next = _head;
            tmp->_prev = NULL;
            _head = tmp;
        }
     }
     
     void popFront()     //头删
     {
         if (_head == _tail)
         {
             if (_head)
             {
                 delete _head;
                 _head = _tail = NULL;
             }
         }
         else
        {
            ListNode<T> * tmp = _head->_next;
            delete _head;
            _head = tmp;
            tmp->_prev = NULL;
        }
     }
     
      void Insert(ListNode<T> * pos,const T& x)    //在pos位置上插入数据x
     {
         assert(pos);
         ListNode<T> * tmp = new ListNode<T>(x);
         ListNode<T> * cur = pos->_next;
         tmp->_next = cur;
         cur->_prev = tmp;
         tmp->_prev = pos;
         pos->_next = tmp;
     }
     
      void Erase(ListNode<T> * pos)    //删除pos位置上的数据
     {
         assert(pos);
         if (_head == NULL)
         {
             return;
          }
         else if (_head == _tail)
         {
             delete _head;
          }
         else
         {
             ListNode<T> * cur = pos->_next;
             ListNode<T> * tmp = pos->_prev;
             tmp->_next = cur;
             cur->_prev = tmp;
             delete pos;
         }
      }
      
      ListNode<T> * Find(const T & x)     //查找
     {
          ListNode<T> * tmp = _head;
          while (tmp)
         {
             if (tmp->_data == x)
            {
                return tmp;
             }
             tmp = tmp->_next;
         }
         if (tmp->_next)
        {
            return NULL;
         }
     }
     
     T & Top()     //读取队头元素
     {
         return _head->_data;
      }
      
     T & Back()     //读取队尾元素
    {
        assert(size > 0);
        return _tail->_data;
     }

     void Reverse()     //逆置
     {
         swap(_head, _tail);
         ListNode<T>* tmp = _head;
         while (tmp)
        {
            swap(tmp->_prev, tmp->_next);
            tmp = tmp->_next;
        }
     }
     
     void Sort()      //冒泡排序
     {
         ListNode<T> * cur = _head;
         ListNode<T> * tmp = _head->_next;
         while (tmp)
         {
             if (cur->_data > tmp->_data)
             {
                 T ptr = cur->_data;
                 cur->_data = tmp->_data;
                 tmp->_data = ptr;
             }
             cur = cur->_next;
             tmp = tmp->_next;
         }
      }
      
     void Unique()    //在有序链表中,去掉重复的数据
    {
        ListNode<T> * cur = _head;
        ListNode<T> * tmp = _head->_next;
        while (tmp)
       {
           while (cur->_data == tmp->_data)
          {
              ListNode<T>* str = tmp;
              tmp = tmp->_next;
              Erase(str);
          }
          cur = cur->_next;
          tmp = tmp->_next;
       }
    }
    
     void Merge(List<T> & s)    //将某一个链表连接到这个链表后面
     {
         _tail->_next = s._head;
         s._head->_prev = _tail;
      }
      
     void Splice(ListNode<T> * pos, List<T> & s)    //将一个链表连接到pos位置后面
    {
        assert(pos);
        if (pos == _tail)
        {
            Merge(s);
        }
        else
       {
            ListNode<T> *  cur = pos;
            ListNode<T> * tmp = pos->_next;
            ListNode<T> * str = s._tail;
            cur->_next = s._head;
            s._head->_prev = cur;
            str->_next = tmp;
            tmp->_prev = str;
        }
    }
    
     size_t Size()    //计算链表中的元素个数
    {
         ListNode<T> * tmp = _head;
         int count = 0;
         while (tmp)
        {
            count++;
            tmp = tmp->_next;
        }
         return count;
     }
     
     void print()   //格式输出
     {
         ListNode<T> * tmp = _head;
         while (tmp)
         {
             cout << tmp->_data << " ";
             tmp = tmp->_next;
          }
         cout << endl;
      }

    void Clear()
    {
        ListNode<T> * tmp = _head;
        while (tmp)
       {
           ListNode<T> * str = tmp;
           tmp = tmp->_next;
           delete str;
       }
    }

private:
    ListNode<T> * _head;
    ListNode<T> * _tail;
};


       对于”队列“能够利用上述双向链表的功能来实现,下面就是基本的程序代码:


#pragma once
#include <string>

//队列
#include <assert.h>
#include "ListNode.h"
template <class T , template<class> class container = List>
class Queue
{
public:
     void push(const T & x)   //进入队列
    {
        _con.pushBack(x);
     }
     
     void pop()         //出队列
    {
        _con.popFront();
     }
     
     bool Empty()    //判断队列是否为空
    {
        return _con.Size() == 0;
     }
     
     size_t size()    //计算队列中的元素个数
    {
        return _con.size();
    }
    
     T & top()    //队头节点
     {
        return _con.Top();
     }
     
     T & Back()    //队尾节点
    {
        return _con.Back();
     }
     
     void print()    //格式输出
    {
        _con.print();
     }
     
private:
     container<T> _con;
};


本文出自 “无心的执着” 博客,谢绝转载!

以上是关于模板(双向链表与队列)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构开发:循环链表与双向链表

数据结构--循环链表与双向链表

双向链表的实现(双向链表与单向链表的简单区别联系和实现)

双向链表的实现(双向链表与单向链表的简单区别联系和实现)

[单向链表与双向链表的实现]

双向链表与LinkedHashMap