LinkQueue

本文介绍了链式队列的基本概念与设计要点,并通过两种不同的链表实现进行了对比。一种是基于普通链表的实现,其在入队操作上存在效率问题;另一种则采用了Linux内核链表,实现了更高效的队列操作。

1 链式队列的概念

对于StaticQueue,当数据元素为类类型时,StaticQueue的对象在创建时,会多次调用元素类型的构造函数,影响效率。我们需要链式队列来解决这个问题。

1.1 队列的链式存储实现

在这里插入图片描述

1.2 链式队列的设计要点

  • 类模板,抽象父类Queue的直接子类。
  • 在内部使用链式结构实现元素的存储。
  • 只在链表的头部和尾部进行操作。

2 使用LinkList实现链式队列

2.1 继承关系图

在这里插入图片描述

2.2 代码实现

LinkQueue.h:

#ifndef LINKQUEUE_H
#define LINKQUEUE_H

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

namespace LemonLib {
template <typename T>
class LinkQueue : public Queue<T>
{
protected:
    LinkList<T> m_list;

public:
    void add(const T &e)
    {
        m_list.insert(e);
    }

    void remove()
    {
        if (m_list.length() > 0)
        {
            m_list.remove(0);
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "remove error, link queue is empty");
        }
    }

    T front() const
    {
        if (m_list.length() > 0)
        {
            return m_list.get(0);
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "front error, link queue is empty");
        }
    }

    void clear()
    {
        m_list.clear();
    }

    int size() const
    {
        return m_list.length();
    }
};
}

#endif // LINKQUEUE_H


3 使用LinuxList实现LinkQueue

我们可以发现使用LinkList实现链式队列,在入队时时间复杂度为O(n),这显然是可以优化的。

3.1 队列链式存储实现的优化

在这里插入图片描述
类的继承关系图如下:
在这里插入图片描述

3.2 代码实现

LinkQueue.h:

#ifndef LINKQUEUE_H
#define LINKQUEUE_H

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

namespace LemonLib {
template <typename T>
class LinkQueue : public Queue<T>
{
protected:
    struct Node : public Object
    {
        list_head head;
        T e;
    };

    list_head m_header;
    int m_length;

public:
    LinkQueue()
    {
        m_length = 0;
        INIT_LIST_HEAD(&m_header);
    }

    void add(const T &e)
    {
        Node* node = new Node();

        if (node != NULL)
        {
            node->e = e;
            list_add_tail(&node->head, &m_header);
            m_length++;
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "linkqueue add error, no enough memory");
        }
    }

    void remove()
    {
        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, "remove error, link queue is empty");
        }
    }

    T front() const
    {
        if (m_length > 0)
        {
            return list_entry(m_header.next, Node, head)->e;
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "front error, link queue is empty");
        }
    }

    void clear()
    {
        while (m_length > 0)
        {
            remove();
        }
    }

    int size() const
    {
        return m_length;
    }

    // 不要忘记提供析构函数
    ~LinkQueue()
    {
        clear();
    }
};
}

#endif // LINKQUEUE_H


4 小结

  • StaticQueue在初始化时可能多次调用元素类型的构造函数。
  • LinkList的组合使用能够实现队列的功能,但是不够高效。
  • LinkQueue的最终实现组合使用了Linux内核链表。
  • LinkQueue中入队和出队操作可以在常量时间内完成。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值