【C++】容器适配器实现队列Queue的各种功能(入队、出队、判空、大小、访问所有元素等)

原创 2016年05月30日 17:18:10

适配器:


将一个通用的容器转换为另外的容器,所谓的容器,指的是存放数据的器具,像我们知道的顺序表和链表都是容器Container。举个例子解释一下吧,我们的电压都是220v,而像充电线就起到转换到合适的电压的作用。而这里,我们的主角就是将通用的链表结构转换为来实现队列Queue这一数据结构,(意思就是,链表还可以去实现其他的数据结构)。


在线性表中,分为链表和顺序表,我们知道其中的差别:


链表:节点灵活,使得插入删除元素方便灵活,但是对于单链表若有节点指针_head、_tail,查找元素较为麻烦,需要遍历。


顺序表:开辟一块连续的内存空间,查找元素方便,通过指针或者下标来访问。插入或者删除元素呢,又较为复杂,插入时需要将后面的元素挨着挨着全部后移,删除元素后又需要将后面的元素全部前移。


针对队列Queue模型,我们知道它是尾插头删、先进先出的特点。因此我针对以上原因选用链表结构来实现队列Queue。可以参照下图:


wKiom1bo06nSvSW8AAAYVK-E-CQ155.png


代码如下:

#include<iostream>
using namespace std;
#include<assert.h>

template<class T>
struct ListNode
{
    ListNode(const T& x)
    :_next(NULL)
    , _prev(NULL)
    , _data(x)
    {}

    ListNode<T>* _next;
    ListNode<T>* _prev;
    T _data;
};

template<class T>
class List
{
public:
    List()
        :_head(NULL)
        , _tail(NULL)
    {}

    List(const List<T>& l)
    {
        ListNode<T>* cur = l._head;
        while (cur)
        {
            this->PushBack(cur->_data);
            cur = cur->_next;
        }
    }

    List<T>& operator=(const List<T>& l)
    {
        //先删除节点,再插入节点
        if (&s != this)
        {
            ListNode<T>* pcur = _head;
            while (pcur)
            {
                ListNode<T>* del = pcur;
                pcur = pcur->_next;
                delete del;
                del = NULL;
            }

            ListNode<T>* cur = _head;
            while (cur)
            {
                this->PushBack(cur->_data);
                cur = cur->_next;
            }
        }
        return *this;
    }

    ~List()//一个节点一个节点的删除
    {
        ListNode<T>* cur = _head;
        while (cur)
        {
            ListNode<T>* del = cur;
            cur = cur->_next;
            delete del;
            del = NULL;
        }
    }

    void PushBack(const T& x);
    void PopBack();
    void PopFront();
    void PrintList();
    void Reverse();
    size_t Length();    

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


//尾插
template<class T>
void List<T>::PushBack(const T& x)
{
    //分析:分为两种情况:无节点、有节点
    if (_head == NULL)
    {
        _head = _tail = new ListNode<T>(x);
    }
    else
    {
        ListNode<T>* cur = new ListNode<T>(x);
        _tail->_next = cur;
        cur->_prev = _tail;
        _tail = cur;
        _tail->_next = NULL;
    }
}

//尾删
template<class T>
void List<T>::PopBack()
{
    //分析:分为三种情况:无节点、一个节点、多个节点
    if (_head == _tail)
    {
        if (_head == NULL)
        {
            return;
        }
        else
        {
            delete _head;
            _head = _tail = NULL;
        }
    }
    else
    {
        ListNode<T>* prev = _tail->_prev;
        delete _tail;
        _tail = NULL;
        _tail = prev;
        _tail->_next = NULL;
    }
}

//头删
template<class T>
void List<T>::PopFront()
{
    if (_head == _tail)
    {
        if (_head == NULL)
        {
            return;
        }
        delete _head;
        _head = _tail = NULL;
    }
    else
    {
        ListNode<T>* cur = _head;
        ListNode<T>* del = _head;    
        _head = cur->_next;
        delete del;
        del = NULL;        
        _head->_prev = NULL;
    }
    
}

//逆置
template<class T>
void List<T>::Reverse()
{
    //分析:从两头开始走,交换数据(分奇数个数据和偶数个数据)
    ListNode<T>* begin = _head;
    ListNode<T>* end = _tail;
    while (!((begin == end) || end->_next == begin))
    {
        swap(begin->_data, end->_data);
        begin = begin->_next;
        end = end->_prev;
    }
}

//长度
template<class T>
size_t List<T>::Length()
{
    ListNode<T>* cur = _head;
    int count = 0;
    while (cur)
    {
        ++count;
        cur = cur->_next;
    }
    return count;
}


//打印
template<class T>
void List<T>::PrintList()
{
    ListNode<T>* cur = _head;
    while (cur)
    {
        cout << cur->_data << "->";
        cur = cur->_next;
    }
    cout << "NULL" << endl;
}

template<class T, template<class> class Container = List>    //缺省形式
class Queue
{
public:
    //入队
    void Push(const T& x)
    {
        _con.PushBack(x);
    }

    //出队
    void Pop()
    {
        _con.PopFront();
    }

    //大小
    size_t Size()
    {
        return _con.Length();
    }

    //判空
    bool Empty()
    {
        return Size() == 0;
    }

    //队头
    T& Front()
    {
        size_t size = Size();
        assert(size > 0);
        return _con._head->_data;
    }

    //队尾
    T& Back()
    {
        size_t size = Size();
        assert(size > 0);
        return _con._tail->_data;
    }

protected:
    Container<T> _con;
};


//队列的测试函数
void TestQueue()
{
    Queue<int, List> q1;
    //Queue<int> q1;
    q1.Push(1);
    q1.Push(2);
    q1.Push(3);
    q1.Push(4);
    q1.Push(5);

    //访问队列所有元素(队列是插尾删头)
    while (!q1.Empty())
    {
        cout<< q1.Front() << "  ";
        q1.Pop();
    }
}


int main()
{
    TestQueue();
    system("pause");
    return 0;
}


本文出自 “Han Jing's Blog” 博客,请务必保留此出处http://10740184.blog.51cto.com/10730184/1751682

C++ STL 队列queue的用法

C++队列queue模板类的定义在头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。     C++队列Queu...
  • cf406061841
  • cf406061841
  • 2017年05月01日 10:36
  • 531

c++容器queue的用法整理

C++队列queue模板类的定义在头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。 C++队列Queue是一种容...
  • fengzhizi76506
  • fengzhizi76506
  • 2017年02月01日 18:48
  • 3438

C++ 栈和队列 Vector

原帖 http://blog.csdn.net/zhy_cheng/article/details/8090346 使用标准库的栈和队列时,先包含相关的头文件 #include ...
  • XingKong_678
  • XingKong_678
  • 2014年08月18日 13:53
  • 3781

c++ 队列queue的几个基本用法

c++ 队列queue的几个基本用法基本性质 queue模板类的定义在头文件中。 队列符合“先进先出”原则的“公平队列”,与栈的“先进后出”原则刚好相反。可以用queueque方式定义。基本操作 ...
  • elbadaernu
  • elbadaernu
  • 2017年03月26日 22:03
  • 1050

程序猿学习资料集

程序猿学习资料集A.面试:1.前端开发面试题1:点击打开链接 2.前端开发面试题2:https://github.com/hawx1993/Front-end-Interview-questio...
  • JavaRuler
  • JavaRuler
  • 2017年12月15日 13:29
  • 198

循环顺序队列(初始化、入队、出队、判空)

采用循环顺序方式存储队列,测试用例为:将0~9入队,然后打印输出,代码如下: #define MAXQSIZE 100 typedef struct { QElemType data[MAXQS...
  • tkp2014
  • tkp2014
  • 2015年07月05日 10:03
  • 723

C/C++知识回顾 队列的出队和入队

#include using namespace std; typedef struct student { int data; struct student *next; }node; type...
  • luchengtao11
  • luchengtao11
  • 2017年03月06日 21:53
  • 1189

C++ Technical Report 1

C++ Technical Report 1 (TR1)(英文)是ISO/IEC TR 19768, C++ Library Extensions(函式库扩充)的一般名称。TR1是一份文件,内容提...
  • Plutus_Lee
  • Plutus_Lee
  • 2012年11月29日 15:55
  • 875

VC++2012编程演练数据结构《6》优先级队列演练

如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。这样,我们就引入了优先级队列 这种数据结构。...
  • yincheng01
  • yincheng01
  • 2012年11月19日 18:26
  • 2011
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【C++】容器适配器实现队列Queue的各种功能(入队、出队、判空、大小、访问所有元素等)
举报原因:
原因补充:

(最多只允许输入30个字)