C++模板链表实现优先级队列
2017-03-25 11:12
597 查看
本文是承接我的上一篇文章,只是将普通队列增加了优先级.实现了一个优先级队列.本文采取的优先级队列的实现方式在于数据增加优先级标志位,在数据进入队列时,根据优先级排序的顺序进入,出队列仍然是从头出.使用该种思想实现的优先级队列.
继承普通链表队列(具体参考http://blog.csdn.net/luanzheng_365/article/details/64518754). 注意需要将普通链表队列的成员变量linkList的访问权限改成protected.
开始时犯了一个错误,在子类中定义
对继承来的父类的linkList,在子类中可以使用强制类型转换.将其转换为PriorityQueueLinkList. 这样做是安全的,因为传入的data本来必须要保证是优先级队列中的结点的数据结构.
关键数据结构PriorityQueueLinkList,继承自QueueLinkList. 重新写enque方法.并利用C++的隐藏,将尾插入方法隐藏,因为优先级队列不适用尾插入暴露在外面. 出队列方法则可以直接使用继承自父类的dequeue.
该队列插入的效率有一定问题,在队列超过10000个元素后,插入效率明显降低.后续考虑使用高效的插入算法进行优化比较.
6.补充一点C++继承过程中基类与派生类指针相互强制转换的知识. 如果开始的指针指向父类,之后强制转换成子类的指针,则通过该指针可以操作子类独有的成员函数(包括子类新写的与子类继承后重写/隐藏的). 但如果父类是虚函数,则不管子类是否覆盖,通过该强制转换的指针访问该函数,仍然是访问的父类函数. 如果开始指针指向子类,将其强制转换为父类指针,则子类新写的函数不可见.但被覆盖过的虚函数除外.该指针操作父类的虚函数,会自动调用子类的对应函数(多态).
测试代码如下:
继承普通链表队列(具体参考http://blog.csdn.net/luanzheng_365/article/details/64518754). 注意需要将普通链表队列的成员变量linkList的访问权限改成protected.
开始时犯了一个错误,在子类中定义
PriorityQueueLinkList<T, capacity> *linkList = NULL;这样,继承过来的方法isEmpty(), isFull()等中使用的linkList仍是父类的linkList,造成错误.原因是,C++编译器会先构造父类结构,之后再构造子类结构.而继承过来的函数在构造父类的时候就确定了.其并不知道子类的成员变量,因此就无法访问. 总之,这里要注意,继承过来的父类的成员函数(public, protected)在子类中可以使用,但是如果成员函数调用了成员变量,该成员变量也需要在子类中被继承才行(如果成员变量在父类中是privated的就会有问题,子类中从新定义同名成员变量没有任何作用也不可能有任何作用).
对继承来的父类的linkList,在子类中可以使用强制类型转换.将其转换为PriorityQueueLinkList. 这样做是安全的,因为传入的data本来必须要保证是优先级队列中的结点的数据结构.
((PriorityQueueLinkList<T, capacity>*)linkList)->enqueueWithPriority(data);
关键数据结构PriorityQueueLinkList,继承自QueueLinkList. 重新写enque方法.并利用C++的隐藏,将尾插入方法隐藏,因为优先级队列不适用尾插入暴露在外面. 出队列方法则可以直接使用继承自父类的dequeue.
该队列插入的效率有一定问题,在队列超过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; }
相关文章推荐
- C++模板链表实现优先级队列
- C++模板链表实现优先级队列
- C++模板链表实现优先级队列
- C++用模板实现双链表和队列
- 优先级队列——用C++模板实现
- C++模板实现优先级队列
- C++用模板实现双链表和队列
- 【C++】模板实现双链表和队列
- 优先级队列 C++ 模板实现
- c++链表的实现及栈队列
- 数据结构(7) 链队列 c++ 模板实现
- 数据结构(2)单链表 c++ 模板实现
- 数据结构学习系列三-单向循环链表(c++实现且应用模板)
- 用链表实现优先级队列
- 队列(queue)的链表(list)实现及循环数组(circular array)实现 C++实现
- 数据结构(6) 顺序队列 c++ 模板实现
- java实现 数据结构:链表、 栈、 队列、优先级队列、哈希表
- C++模板实现队列
- 数据结构(3)单循环链表 c++ 模板实现
- c++链表实现队列