赞
踩
队列的存储结构有链式和数组两种形式,链式队列较为简单,可以直接通过链表获得,而用数组实现队列则有很多细节,后文中会给出来,本文默认大家已经了解队列的先入先出的特点,重点在于代码实现,如果读者对队列还不熟悉建议先看看书或者视频再来看本文。
由于我们队列的两种形式都要实现,而两种队列的基本操作其实都是一样的,只不过是函数的实现不同,所以我们定义了抽象类
template<class Type>
class queueADT
{
public:
virtual bool isEmpty()const = 0;
virtual bool isFull()const = 0;
virtual void initializeQueue() = 0;
virtual Type front()const = 0;
virtual Type back()const = 0;
virtual void addElem(const Type&) = 0;
virtual void deleteElem() = 0;
virtual int queueLen()const = 0;
};
然后通过类的继承来构造数组队列类,我们将数组的最大容量作为成员变量方便初始化。
template<class Type> class queueArr :public queueADT<Type> { public: const queueArr<Type>& operator=(const queueArr<Type>&); bool isEmpty()const; bool isFull()const; void initializeQueue(); Type front()const; Type back()const; int queueLen()const; void addElem(const Type&); void deleteElem(); queueArr(int size = 100); //设置默认最大数组长度 queueArr(const queueArr<Type>&); ~queueArr(); void printQueue()const; private: int maxSize; int head; int tail; Type* headPtr; };
template<class Type>
bool queueArr<Type>::isEmpty()const
{
return tail == head;
}
注意:我们这里采用的区别队列满和空的手段是在数组中空一个位置,和王卓老师视频里用的方法一样,实际上比较简单的是将当前的元素数目作为成员变量,tail指针指向的是空置的位置。
template<class Type>
bool queueArr<Type>::isFull()const
{
return (tail+1)%maxSize == head;
}
template<class Type>
void queueArr<Type>::initializeQueue()
{
head = 0;
tail = 0;
}
template<class Type>
Type queueArr<Type>::front()const
{
assert(!isEmpty()); //防止队列为空返回错误值
return headPtr[head];
}
template<class Type>
Type queueArr<Type>::back()const
{
assert(!isEmpty());
return headPtr[(tail-1+maxSize)%maxSize];
//注意tail如果为0那么减去1就会是负数,因此要加上数组容量,同时为了防止加了之后的
//索引值超过了数组最大容量,所以要对maxSize取余
}
template<class Type>
int queueArr<Type>::queueLen()const
{
return (tail - head + maxSize) % maxSize;
}
注意:在数组队列中凡是涉及到指针的加减,通通要取余数,如果经过加减后可能出现负数,那么在取余前还要加上数组最大长度。循环计数的精髓就是要取余。
template<class Type>
void queueArr<Type>::addElem(const Type& elem)
{
if (!isFull())
{
headPtr[tail] = elem;
tail = (tail + 1) % maxSize;
}
else
cout << "The queue is full,can not add an element in it" << endl;
}
template<class Type>
void queueArr<Type>::deleteElem()
{
if (!isEmpty())
head = (head + 1) % maxSize;
else
cout << "can not remove an element from the queue" << endl;
}
template<class Type> queueArr<Type>::queueArr(int size) { if (size <= 0) { cout << "Size of the array to hold the queue must " << "be positive." << endl; cout << "Creating an array of size 100." << endl; maxSize = 100; headPtr = new Type[maxSize]; assert(headPtr != nullptr); } else { maxSize = size; head = 0; tail = 0; headPtr = new Type[maxSize]; assert(headPtr != nullptr); //记得判断内存是否分配成功 } }
template<class Type>
queueArr<Type>::queueArr(const queueArr<Type>& otherQueue)
{
head = otherQueue.head;
tail = otherQueue.tail;
maxSize = otherQueue.maxSize;
headPtr = new Type[maxSize];
assert(headPtr != nullptr);
for (int i = 0; i < otherQueue.queueLen(); i++)
headPtr[(head + i) % maxSize] = otherQueue.headPtr[(head + i) % maxSize];//特别注意,拷贝必须从队头开始拷贝(即从head处开始),一直拷贝到队尾,拷贝长度就是队列的长度
}
template<class Type>
queueArr<Type>::~queueArr()
{
delete[]headPtr;
}
template<class Type> const queueArr<Type>& queueArr<Type>::operator=(const queueArr<Type>& otherQueue) { if (this != &otherQueue) { head = otherQueue.head; tail = otherQueue.tail; if (maxSize != otherQueue.maxSize) { delete[]headPtr; headPtr = new Type[otherQueue.maxSize]; assert(headPtr != nullptr); } maxSize = otherQueue.maxSize; if (!otherQueue.isEmpty()) { for (int i = 0; i < otherQueue.queueLen(); i++) headPtr[(head+i)%maxSize] = otherQueue.headPtr[(head + i) % maxSize]; //神来之笔,不然因为空了一个元素,而且元素位置不确定,一旦赋值就会出现问题 } } else { cout << "cannot self assignment" << endl; } return *this; }
template<class Type>
void queueArr<Type>::printQueue()const
{
if (!isEmpty())
{
cout << "The queue:";
for (int i = 0; i < queueLen(); i++)
{
cout << headPtr[(head + i) % maxSize] << " ";
}
cout << endl;
}
}
链式队列很多操作和链表类似,也可以直接从链表获得,这里就不详细介绍了,不过还是给出代码以供参考。
#pragma once #include<iostream> using namespace std; template<class Type> class queueADT { public: virtual bool isEmpty()const = 0; virtual bool isFull()const = 0; virtual void initializeQueue() = 0; virtual Type front()const = 0; virtual Type back()const = 0; virtual void addElem(const Type&) = 0; virtual void deleteElem() = 0; virtual int queueLen()const = 0; };
#pragma once #include<iostream> #include<assert.h> #include "queueADT.h" template<class Type> class queueArr :public queueADT<Type> { public: const queueArr<Type>& operator=(const queueArr<Type>&); bool isEmpty()const; bool isFull()const; void initializeQueue(); Type front()const; Type back()const; int queueLen()const; void addElem(const Type&); void deleteElem(); queueArr(int size = 100); queueArr(const queueArr<Type>&); ~queueArr(); void printQueue()const; private: int maxSize; int head; int tail; Type* headPtr; }; template<class Type> bool queueArr<Type>::isEmpty()const { return tail == head; } template<class Type> bool queueArr<Type>::isFull()const { return (tail+1)%maxSize == head; } template<class Type> void queueArr<Type>::initializeQueue() { head = 0; tail = 0; } template<class Type> Type queueArr<Type>::front()const { assert(!isEmpty()); return headPtr[head]; } template<class Type> Type queueArr<Type>::back()const { assert(!isEmpty()); return headPtr[(tail-1+maxSize)%maxSize]; } template<class Type> int queueArr<Type>::queueLen()const { return (tail - head + maxSize) % maxSize; } template<class Type> void queueArr<Type>::addElem(const Type& elem) { if (!isFull()) { headPtr[tail] = elem; tail = (tail + 1) % maxSize; } else cout << "The queue is full,can not add an element in it" << endl; } template<class Type> void queueArr<Type>::deleteElem() { if (!isEmpty()) head = (head + 1) % maxSize; else cout << "can not remove an element from the queue" << endl; } template<class Type> queueArr<Type>::queueArr(int size) { if (size <= 0) { cout << "Size of the array to hold the queue must " << "be positive." << endl; cout << "Creating an array of size 100." << endl; maxSize = 100; headPtr = new Type[maxSize]; assert(headPtr != nullptr); } else { maxSize = size; head = 0; tail = 0; headPtr = new Type[maxSize]; assert(headPtr != nullptr); //记得判断内存是否分配成功 } } template<class Type> queueArr<Type>::queueArr(const queueArr<Type>& otherQueue) { head = otherQueue.head; tail = otherQueue.tail; maxSize = otherQueue.maxSize; headPtr = new Type[maxSize]; assert(headPtr != nullptr); for (int i = 0; i < otherQueue.queueLen(); i++) headPtr[(head + i) % maxSize] = otherQueue.headPtr[(head + i) % maxSize]; } template<class Type> queueArr<Type>::~queueArr() { delete[]headPtr; } template<class Type> const queueArr<Type>& queueArr<Type>::operator=(const queueArr<Type>& otherQueue) { if (this != &otherQueue) { head = otherQueue.head; tail = otherQueue.tail; if (maxSize != otherQueue.maxSize) { delete[]headPtr; headPtr = new Type[otherQueue.maxSize]; assert(headPtr != nullptr); } maxSize = otherQueue.maxSize; if (!otherQueue.isEmpty()) { for (int i = 0; i < otherQueue.queueLen(); i++) headPtr[(head+i)%maxSize] = otherQueue.headPtr[(head + i) % maxSize]; //神来之笔,不然因为空了一个元素,而且元素位置不确定,一旦赋值就会出现问题 } } else { cout << "cannot self assignment" << endl; } return *this; } template<class Type> void queueArr<Type>::printQueue()const { if (!isEmpty()) { cout << "The queue:"; for (int i = 0; i < queueLen(); i++) { cout << headPtr[(head + i) % maxSize] << " "; } cout << endl; } }
#pragma once #include<iostream> #include<assert.h> #include "queueADT.h" using namespace std; template<class Type> struct node { Type elem; node<Type>* next; }; template<class Type> class queueLink:public queueADT<Type> { public: bool isEmpty()const ; bool isFull()const ; void initializeQueue() ; Type front()const ; Type back()const ; void addElem(const Type&) ; void deleteElem() ; int queueLen()const ; queueLink(); queueLink(const queueLink<Type>&); ~queueLink(); const queueLink<Type>& operator=(const queueLink<Type>&); private: node<Type>* head; node<Type>* tail; int length; void copyQueue(const queueLink<Type>&); }; template<class Type> bool queueLink<Type> ::isEmpty()const { return head == nullptr; } template<class Type> bool queueLink<Type> ::isFull()const { return false; } template<class Type> void queueLink<Type>::initializeQueue() { node<Type>* temp = head; while (head) { head = head->next; delete temp; temp = head; } tail = nullptr; length = 0; } template<class Type> Type queueLink<Type>::front()const { assert(!isEmpty()); return head->elem; } template<class Type> Type queueLink<Type>::back()const { assert(!isEmpty()); return tail->elem; } template<class Type> void queueLink<Type>::addElem(const Type& elem) { node<Type>* newNode = new node<Type>; newNode->elem = elem; newNode->next = nullptr; if (head == nullptr) { tail = newNode; head = newNode; } else { tail->next = newNode; tail = tail->next; } length++; } template<class Type> void queueLink<Type>::deleteElem() { if (!isEmpty()) { node<Type>* temp = head; head = head->next; delete temp; length--; } else cout << "The queue is empty,cannot remove an element" << endl; } template<class Type> int queueLink<Type>::queueLen()const { return length; } template<class Type> queueLink<Type>::queueLink() { head = nullptr; tail = head; length = 0; } template<class Type> queueLink<Type>::~queueLink() { initializeQueue(); } template<class Type> void queueLink<Type>::copyQueue(const queueLink<Type>& otherQueue) { node<Type>* temp,otherCurrent; otherCurrent = otherQueue.head; if (head) initializeQueue(); if (otherQueue.head) { head = new node<Type>; tail = head; head->elem = otherCurrent->elem; head->next = otherCurrent->next; otherCurrent = otherCurrent->next; length++; while (otherCurrent) { temp = new node<Type>; temp->next = otherCurrent->next; temp->elem = otherCurrent->elem; tail->next = temp; tail = tail->next; otherCurrent = otherCurrent->next; length++; } } } template<class Type> queueLink<Type>::queueLink(const queueLink<Type>& otherQueue) { copyQueue(otherQueue); } template<class Type> const queueLink<Type>& queueLink<Type>::operator=(const queueLink<Type>& otherQueue) { if (this != &otherQueue) { copyQueue(otherQueue); } return *this; }
#include<iostream> #include "queueArr.h" #include "queueLink.h" using namespace std; int main() { queueArr<int> que1,que2(4); que1.addElem(11); que1.addElem(12); que1.addElem(13); que1.addElem(13); que1.addElem(13); que1.printQueue(); cout << que1.queueLen() << endl; que1.deleteElem(); que1.addElem(44); que1.deleteElem(); que1.addElem(32); que2 = que1; que1.printQueue(); que2.printQueue(); queueArr<int> que3(que1); que3.printQueue(); que1.printQueue(); cout << que1.queueLen() << endl; que2 = que1; que2.printQueue(); que2.deleteElem(); que2.deleteElem(); que2.deleteElem(); cout << que1.front() << "," << que1.back() << endl; queueLink<int> queL1,queL2; queL1.addElem(13); queL1.addElem(76); cout << queL1.front()<<" " << queL1.back(); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。