DTLib - Queue、StaticQueue、LinkQueue

目录

1、队列的概念及实现

2、基于顺序存储结构的队列 

3、编程实验 

4、基于链式存储结构的队列 

5、编程实验

6、编程实验 

7、小结


1、队列的概念及实现

            队列是一种特殊的线性表 

            队列仅能在线性表的两端进行操作 

      -队头(Front) : 取出数据元素的一端 

      -队尾(Rear) : 插入数据元素的一端

队列的特性 

      -先进先出(First In First Out) 

队列的操作 

      -创建队列( Queue() )  

      -销毁队列( ~Queue() ) 

      -清空队列( clear() ) 

      -进队列( add() ) 

      -出队列( remove() ) 

      -获取队头元素( front() ) 

      -获取队列的长度( length() )

队列的实现

//Queue.h
#ifndef QUEUE_H
#define QUEUE_H

#include "Object.h"

namespace DTLib
{

template <typename T>
class Queue : public Object
{
public:
    virtual void add(const T& e) = 0;
    virtual void remove() = 0;
    virtual T front() const = 0;
    virtual void clear() = 0;
    virtual int length() const = 0;
};
}
#endif // QUEUE_H

2、基于顺序存储结构的队列 

队列的顺序实现 

StaticQueue设计要点  

      -使用原生数组作为队列的存储空间 

      -使用模板参数决定队列的最大容量 

StaticQueue实现要点(循环计数法) 

      -关键操作

                  进队列: m_space[m_rear] = e; m_rear = (m_rear + 1) % N; 

                  出队列: m_front = (m_front + 1) % N; 

      -队列的状态 

                  队空: (m_length == 0) && (m_front == m_rear) 

                  队满: (m_length == N) && (m_front == m_rear)

3、编程实验 

基于顺序存储结构的队列     StaticQueue.h

#ifndef STATICQUEUE_H
#define STATICQUEUE_H

#include "Queue.h"
#include "Exception.h"

namespace DTLib
{

template <typename T, int N>
class StaticQueue : public Queue<T>
{
protected:
    T m_space[N]; //当前队列存储空间
    int m_front; //队头标识
    int m_rear; //队尾标识
    int m_length; //当前队列长度
public:
    StaticQueue()
    {
        m_front = 0;
        m_rear = 0;
        m_length = 0;
    }

    void add(const T& e)
    {
        if(m_length < N)
        {
            m_space[m_rear] = e;
            m_rear = (m_rear + 1) % N;
            m_length++;
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No space in current queue ...");
        }
    }

    void remove()
    {
        if(m_length > 0)
        {
            m_front = (m_front + 1) % N;
            m_length--;
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No space in current queue ...");
        }
    }

    T front() const
    {
        if(m_length > 0)
        {
            return m_space[m_front];
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No space in current queue ...");
        }
    }

    void clear()
    {
        m_front = 0;
        m_rear = 0;
        m_length = 0;
    }

    int length() const
    {
        return m_length;
    }

    int capacity() const
    {
        return N;
    }
};
}

#endif // STATICQUEUE_H

main.cpp

#include <iostream>
#include "StaticQueue.h"

using namespace std;
using namespace DTLib;

int main()
{
    StaticQueue<int, 5> queue;

    for(int i = 0; i < 5; i++)
    {
        queue.add(i);
    }

    while(queue.length() > 0)
    {
        cout << queue.front() << endl;

        queue.remove();
    }

    return 0;
}

 

 

4、基于链式存储结构的队列 

队列的链式存储实现 

链式队列的设计要点 

      -类模板,抽象父类Queue的直接子类 

      -在内部使用链式结构实现元素的存储 

      -只在链表的头部尾部进行操作 

链式队列的设计要点 

 

5、编程实验

基于LinkList的队列     LinkQueue.h 

#ifndef LINKQUEUE_H
#define LINKQUEUE_H

#include "Queue.h"
#include "LinkList.h"
#include "Exception.h"

namespace DTLib
{

template <typename T>
class LinkQueue : public Queue<T>
{
protected:
    LinkList<T> m_list;
public:
    LinkQueue()
    {

    }

    void add(const T& e) //O(n)
    {
        m_list.insert(e);
    }

    void remove() //O(1)
    {
        if(m_list.length() > 0)
        {
            m_list.remove(0);
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
        }
    }
    
    T front() const //O(1)
    {
        if(m_list.length() > 0)
        {
            return m_list.get(0);
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
        }
    }
    
    void clear() //O(n)
    {
        m_list.clear();
    }
    
    int length() const //O(1)
    {
        return m_list.length();
    }
};
}

#endif // LINKQUEUE_H

会发现基于单链表的链式队列并不高效(对比)

 

队列链式存储实现的优化

链式队列的设计优化 

6、编程实验 

基于Linux内核链表的队列     LinkQueue.h 

#ifndef LINKQUEUE_H
#define LINKQUEUE_H

#include "Queue.h"
#include "LinuxList.h"
#include "Exception.h"

namespace DTLib
{

template <typename T>
class LinkQueue : public Queue<T>
{
protected:
    struct Node : public Object
    {
        list_head head;
        T value;
    };
    
    list_head m_header;//头结点
    int m_length;//当前队列长度
public:
    LinkQueue()
    {
        m_length = 0;
        
        INIT_LIST_HEAD(&m_header);
    }
    
    void add(const T& e) //O(1)
    {
        Node* node = new Node();
        
        if( node )
        {
            node->value = e;
            
            list_add_tail(&node->head, &m_header);
            
            m_length++;
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to add new element ...");
        }
    }
    
    void remove() //O(1)
    {
        if(m_length > 0)
        {
            list_head* toDel = m_header.next;
            
            list_del(toDel);
            
            m_length--;
            
            delete list_entry(toDel, Node, head);
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
        }
    }
    
    T front() const //O(1)
    {
        if(m_length > 0)
        {
            return list_entry(m_header.next, Node, head)->value;
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
        }
    }
    
    void clear() //O(n)
    {
        while(m_length > 0)
        {
            remove();
        }
    }
    
    int length() const
    {
        return m_length;
    }
    
    ~LinkQueue() //O(n)
    {
        clear();
    }
};
}

#endif // LINKQUEUE_H

 

7、小结

            队列是一种特殊的线性表,具有先进先出的特性 

            队列只允许在线性表的两端进行操作,一端进,一端出

            StaticQueue使用原生数组作为内部存储空间

            StaticQueue的最大容量由模板参数决定 

            StaticQueue采用循环计数法提高队列操作的效率 

            StaticQueue在初始化时可能多次调用元素类型的构造函数 

            LinkList的组合使用能够实现队列的功能,但是不够高效

            LinkQueue的最终实现组合使用了Linux内核链表 

            LinkQueue中入队和出队操作可以在常量时间内完成 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值