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

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

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

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

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

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

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

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

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

}

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

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

}

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



template<typename T, const unsigned int capacity>
bool PriorityQueueLinkList::enqueueWithPriority(T data)
{
    bool rs = false;
    if (isFull())
    {
        rs = false;
    }
    else
    {
        if (isEmpty())
        {
            LinkNode *node = new LinkNode();
            node->data = data;
            node->next = NULL;
            head->next = node;
            tail = node;
            linkNodeNum++;
            rs = true;
        }
        else
        {
            LinkNode *iter = head->next;
            LinkNode *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 *node = new LinkNode();
                    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::enqueueAtTail(T data)
{
    return QueueLinkList::enqueueAtTail(data);     //默认实现,目的在于隐藏该方法
}

测试代码如下:

void testPriorityQueue()
{
    PriorityLinkQueueint>, 30000> *priorityLinkQueue = new PriorityLinkQueueint>, 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;
}

你可能感兴趣的:(C/C++,数据结构与算法)