C++模板链表实现优先级队列

本文是承接我的上一篇文章,只是将普通队列增加了优先级.实现了一个优先级队列.本文采取的优先级队列的实现方式在于数据增加优先级标志位,在数据进入队列时,根据优先级排序的顺序进入,出队列仍然是从头出.使用该种思想实现的优先级队列.

  1. 继承普通链表队列(具体参考http://blog.csdn.net/luanzheng_365/article/details/64518754). 注意需要将普通链表队列的成员变量linkList的访问权限改成protected.

  2. 开始时犯了一个错误,在子类中定义PriorityQueueLinkList<T, capacity> *linkList = NULL;这样,继承过来的方法isEmpty(), isFull()等中使用的linkList仍是父类的linkList,造成错误.原因是,C++编译器会先构造父类结构,之后再构造子类结构.而继承过来的函数在构造父类的时候就确定了.其并不知道子类的成员变量,因此就无法访问. 总之,这里要注意,继承过来的父类的成员函数(public, protected)在子类中可以使用,但是如果成员函数调用了成员变量,该成员变量也需要在子类中被继承才行(如果成员变量在父类中是privated的就会有问题,子类中从新定义同名成员变量没有任何作用也不可能有任何作用).

  3. 对继承来的父类的linkList,在子类中可以使用强制类型转换.将其转换为PriorityQueueLinkList. 这样做是安全的,因为传入的data本来必须要保证是优先级队列中的结点的数据结构.((PriorityQueueLinkList<T, capacity>*)linkList)->enqueueWithPriority(data);

  4. 关键数据结构PriorityQueueLinkList,继承自QueueLinkList. 重新写enque方法.并利用C++的隐藏,将尾插入方法隐藏,因为优先级队列不适用尾插入暴露在外面. 出队列方法则可以直接使用继承自父类的dequeue.

  5. 该队列插入的效率有一定问题,在队列超过10000个元素后,插入效率明显降低.后续考虑使用高效的插入算法进行优化比较.

6.补充一点C++继承过程中基类与派生类指针相互强制转换的知识. 如果开始的指针指向父类,之后强制转换成子类的指针,则通过该指针可以操作子类独有的成员函数(包括子类新写的与子类继承后重写/隐藏的). 但如果父类是虚函数,则不管子类是否覆盖,通过该强制转换的指针访问该函数,仍然是访问的父类函数. 如果开始指针指向子类,将其强制转换为父类指针,则子类新写的函数不可见.但被覆盖过的虚函数除外.该指针操作父类的虚函数,会自动调用子类的对应函数(多态).

template<typename T, unsigned int capacity>
class PriorityLinkQueue : public LinkQueue<T, capacity>
{
public:
    PriorityLinkQueue();
    ~PriorityLinkQueue();
    bool enQueue(T data);
//private:
//  PriorityQueueLinkList<T, capacity> *linkList = NULL;
};
template <typename T, unsigned int capacity>
PriorityLinkQueue<T, capacity>::PriorityLinkQueue()
{

}

template <typename T, unsigned int capacity>
PriorityLinkQueue<T, capacity>::~PriorityLinkQueue()
{
    cout << "PriorityLinkQueue destructor called" << endl;
}

template <typename T, unsigned int capacity>
bool PriorityLinkQueue<T, capacity>::enQueue(T data)
{
    /*开始时犯了一个错误,在子类中定义PriorityQueueLinkList<T, capacity> *linkList = NULL;
    这样,继承过来的方法isEmpty(), isFull()等中使用的linkList仍是父类的linkList,造成错误.
    原因是,C++编译器会先构造父类结构,之后再构造子类结构.而继承过来的函数在构造父类的时候
    就确定了.其并不知道子类的成员变量,因此就无法访问.*/
    return ((PriorityQueueLinkList<T, capacity>*)linkList)->enqueueWithPriority(data);
}
template <typename T, const unsigned int capacity>
class PriorityQueueLinkList : public QueueLinkList<T, capacity>
{
public:
    PriorityQueueLinkList();
    ~PriorityQueueLinkList();
    bool enqueueWithPriority(T data);
private:
    bool enqueueAtTail(T data);  //利用C++的隐藏,将尾插入方法隐藏,因为优先级队列不适用尾插入暴露在外面
};
template<typename T, const unsigned int capacity>
PriorityQueueLinkList<T, capacity>::PriorityQueueLinkList()
{

}

template<typename T, const unsigned int capacity>
PriorityQueueLinkList<T, capacity>::~PriorityQueueLinkList()
{
    cout << "PriorityQueueLinkList destructor called" << endl;
}



template<typename T, const unsigned int capacity>
bool PriorityQueueLinkList<T, capacity>::enqueueWithPriority(T data)
{
    bool rs = false;
    if (isFull())
    {
        rs = false;
    }
    else
    {
        if (isEmpty())
        {
            LinkNode<T> *node = new LinkNode<T>();
            node->data = data;
            node->next = NULL;
            head->next = node;
            tail = node;
            linkNodeNum++;
            rs = true;
        }
        else
        {
            LinkNode<T> *iter = head->next;
            LinkNode<T> *preIter = head;
            while (NULL != iter)
            {
                unsigned int priority = iter->data.priority;
                if (data.priority >= priority)
                {
                    preIter = iter;
                    iter = iter->next;
                }
                else
                {
                    //insert after preIter and before iter
                    LinkNode<T> *node = new LinkNode<T>();
                    node->data = data;
                    preIter->next = node;
                    node->next = iter;
                    linkNodeNum++;
                    rs = true;
                    break;
                }
            }
            if (NULL == iter)
            {
                rs = enqueueAtTail(data);
            }
        }
    }
    return rs;
}


template<typename T, const unsigned int capacity>
bool PriorityQueueLinkList<T, capacity>::enqueueAtTail(T data)
{
    return QueueLinkList<T, capacity>::enqueueAtTail(data);     //默认实现,目的在于隐藏该方法
}

测试代码如下:

void testPriorityQueue()
{
    PriorityLinkQueue<PriorityQueueNode<int>, 30000> *priorityLinkQueue = new PriorityLinkQueue<PriorityQueueNode<int>, 30000>();

    unsigned int num = 0;
    while (num<2)
    {
        num++;
        cout << "NUM:" << num << endl;
        for (int i = 0; i < 40000; i++)
        {
            PriorityQueueNode<int> prioQueueNode;
            prioQueueNode.priority = (i % 5);
            prioQueueNode.data = i;

            priorityLinkQueue->enQueue(prioQueueNode);
        }

        _sleep(2000);

        for (int i = 0; i < 35000; i++)
        {
            PriorityQueueNode<int> deQueueNode;
            priorityLinkQueue->deQueue(deQueueNode);
        }

        _sleep(2000);
    }

    for (int i = 0; i < 40000; i++)
    {
        PriorityQueueNode<int> prioQueueNode;
        prioQueueNode.priority = (i % 5);
        prioQueueNode.data = i;

        priorityLinkQueue->enQueue(prioQueueNode);
    }

    delete priorityLinkQueue;
    priorityLinkQueue = NULL;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值