头文件queue.h:
#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED
const int maxSize = 50;
enum bool{false,true};
template<typename T>
class Queue
{
public:
Queue(){};
~Queue(){};
virtual void EnQueue(const T& x) = 0;
virtual void DeQueue(T& x) = 0;
virtual bool getFront(T& x) = 0;
virtual bool IsEmpty()const = 0;
virtual bool IsFull()const = 0;
virtual int getSize()const = 0;
};
template <typename T>
struct LinkNode
{
T data;
LinkNode<T> *link;
LinkNode(LinkNode<T>* ptr = NULL){link = ptr;}
void LinkNOde(const T& item, LinkNode<T> *ptr = NULL)
{
data = item;
link = ptr;
}
};
#endif // QUEUE_H_INCLUDED
实现函数queue_list.cpp:
#include <iostream>
#include "queue.h"
using namespace std;
template <typename T>
class LinkedQueue:public Queu<T>
{
public:
LinkedQueue():rear(NULL),myfront(NULL){}
~LinkedQueue(makeEmpty());
bool EnQueue(const T& x);
bool DeQueue(T& x);
bool getFront(T& x)const;
void makeEmpty();
bool IsEmpty()const{return (myfront == NULL) ? true : false;}
int getSize()const;
friend ostream& operator<<(ostream& os, LinkedQueue<T>& Q);
protected:
LinkNode *myfront, *rear;
};
template <typename T>
void LinkedQueue<T>::makeEmpty()
{
LinkNode<T> *p;
while(myfront != NULL)
{
p = myfront;
myfront = myfront->link;
delete p;
}
}
template <typename T>
bool LinkedQueue<T>::EnQueue(const T& x)
{
if(myfront == NULL)//判断是不是空队列
{
myfront =rear = new LinkNode<T>(x);
if(myfront == NULL)
return false;
}
else
{
rear->link = new LinkNode<T>(x);
if(rear->link == NULL) return false;
rear = rear->link;
}
return true;
}
template <typename T>
bool LinkedQueue<T>::DeQueue(T& x)
{
if(IsEmpty () == true) return false;
LinkNode<T> *p = myfront;
x = myfront->data;
myfront = myfront->link;
delete p;
return true;
}
template <typename T>
bool LinkedQueue<T>::getFront(T& x)
{
if(IsEmpty() == true) return false;
x = myfront->data;
return true;
}
template <typename T>
int LinkedQueue<T>::getSize()const
{
LinkNode<T> *p = myfront;
int k = 0;
while(p != NULL)
{
p = p->link;
k++;
}
}
template <typename T>
ostream& operator<<(ostream& os,LinkedQueue<T>& Q)
{
os<<"队列中的元素个数有"<<Q.getSize()<<endl;
LinkNode<T> *p;
int i = 0;
while(p != NULL)
{
os<<++i<<":"<<p->data<<endl;
p = p->link;
}
return os;
}
代码均通过CB编译。用单链表表示的链式队列特别适合于数据元素变动比较大的情形,而且不存在队列满溢出的情况。上述为一般的队列(用链表实现)
我记得刚开始学数据结构的时候,听的是浙江大学的数据结构,跟完一遍课之后发现根本就没有懂。比如说在删除的时候为什么要先判空啊;在遍历队列中的元素时为什么要重新申请一个节点指针,使它指向队头的节点。
为了解决假溢出的问题,我们提出了一种循环队列。还是用数组的方式来存储数据。
头文件:
#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED
//int maxSize = 50;
//enum bool{false,true};
template<typename T>
class Queue
{
public:
Queue(){};
~Queue(){};
virtual bool EnQueue(const T& x) = 0;
virtual bool DeQueue(T& x) = 0;
virtual bool getFront(T& x) = 0;
virtual bool IsEmpty()const = 0;
virtual bool IsFull()const = 0;
virtual int getSize()const = 0;
};
template <typename T>
struct LinkNode
{
T data;
LinkNode<T> *link;
LinkNode(LinkNode<T>* ptr = NULL){link = ptr;}
void LinkNOde(const T& item, LinkNode<T> *ptr = NULL)
{
data = item;
link = ptr;
}
};
#endif // QUEUE_H_INCLUDED
循环链表的实现:
#include <assert.h>
#include <iostream>
#include "Queue.h"
using namespace std;
template <typename T>
class SeqQueue:public Queue<T>
{
public:
SeqQueue(int sz = 10);
~SeqQueue()
{
delete[]elements;
}
bool EnQueue(const T& x);
bool DeQueue(T& x);
bool getFront(T& x);
void makeEmpty()
{
myfront = rear = 0;
}
bool IsEmpty()const
{
return (myfront == rear) ? true : false;
}
bool IsFull()const
{
return ((rear + 1) % maxSize == myfront) ? true : false;
}
int getSize()const
{
return(rear - myfront + maxSize) % maxSize;
}
int getMaxSize()const
{
return maxSize;
}
template <typename U>
friend ostream& operator << (ostream& os, SeqQueue<U>& Q);
protected:
int rear,myfront;
T *elements;
int maxSize;
};
template <typename T>
SeqQueue<T>::SeqQueue(int sz):myfront(0),rear(0),maxSize(sz)
{
elements = new T[maxSize];
assert(elements != NULL);
}
template <typename T>
bool SeqQueue<T>::EnQueue(const T& x)
{
if(IsFull() == true) return false;
elements[rear] = x;
rear = (rear + 1) % maxSize;
return true;
}
template <typename T>
bool SeqQueue<T>::DeQueue(T& x)
{
if(IsEmpty() == true) return false;
x = elements[myfront];
myfront = (myfront + 1) % maxSize;
return true;
}
template <typename T>
bool SeqQueue<T>::getFront(T& x)
{
if(IsEmpty() == true) return false;
x = elements[myfront];
return true;
}
template <typename U>
ostream& operator << (ostream& os, SeqQueue<U>& Q)
{
os << "myfront = " << Q.myfront << ",rear = " << Q.rear << endl;
for(int i = Q.myfront; i != Q.rear;i = (i + 1) % Q.maxSize )
os << i <<":" << Q.elements[i] << endl;
return os;
}
int main()
{ int x;
SeqQueue<int> myqueue(8);
cout << myqueue.getMaxSize() << endl;
myqueue.EnQueue(100);
myqueue.EnQueue(1);
myqueue.EnQueue(1);
myqueue.EnQueue(1);
myqueue.EnQueue(1);
myqueue.EnQueue(1);
myqueue.EnQueue(1);
//myqueue.EnQueue(1);
myqueue.DeQueue(x);
cout<< x << endl;
myqueue.EnQueue(200);
myqueue.EnQueue(200);
cout<< "myqueue: " << myqueue <<endl;
}
我在编的时候参考的是殷人昆主编的第二版的《C++数据结构》,书里面还是有不少的问题。难道是编译环境有所差别?
PS:在调试的时候有些地方值得注意:
首先,在用友元函数重载类SeqQueue的operator << 时候,编译器报错。原因是该友元函数在类中的声明使用template<typename T> 构成了对类的依赖,而友元函数相对于类是独立的,它不应该对类构成依赖。google之后参考了他人的博客解决了问题。解决问题的办法主要有两种。第一种:将友元函数的实现放在类的内部。第二种:在类的内部声明友元函数的时候为它单独配一个模板类型,然后在外部实现。我代码里面用的是第二种方法,经过调试第一种方法也是可行的。
第二,书中好多地方代码都是有误的,比如此程序中的重载输出运算符的函数中,在访问SeqQueue类型Q对象的私有成员的时候应该是以Q.maxSize,Q.myfront,Q.rear的形式来访问的,否则咋访问数据时候可能出现歧义。
第三,程序仍有一些存在风险的警告,仍需后续的解决。
队列还有补充的内容,还有为什么富文本编辑器的水平线删除不掉。。。
借助vector实现队列(存在假溢出的情况)PS:简单但是很低效。。。
#include <iostream>
#include <vector>
using namespace std;
class MyQueue{
vector<int> data;
int p_start;
public:
MyQueue(){p_start = 0;}
bool enQueue(int x){
data.push_back(x);
return true;
}
bool deQueue(){
if(isEmpty()) return false;
++p_start;
return true;
}
int Front(){
return data[p_start];
}
bool isEmpty()
{
return p_start >= data.size();
}
};
int main() {
MyQueue q;
q.enQueue(5);
q.enQueue(3);
if (!q.isEmpty()) {
cout << q.Front() << endl;
}
q.deQueue();
if (!q.isEmpty()) {
cout << q.Front() << endl;
}
q.deQueue();
if (!q.isEmpty()) {
cout << " q.Front()"<< endl;
}
}
借助vector的循环队列的实现
class MyCircularQueue {
private:
vector<int> data;
int head;
int tail;
int size;
public:
/** Initialize your data structure here. Set the size of the queue to be k. */
MyCircularQueue(int k) {
data.resize(k);
head = -1;
tail = -1;
size = k;
}
/** Insert an element into the circular queue. Return true if the operation is successful. */
bool enQueue(int value) {
if (isFull()) {
return false;
}
if (isEmpty()) {
head = 0;
}
tail = (tail + 1) % size;
data[tail] = value;
return true;
}
/** Delete an element from the circular queue. Return true if the operation is successful. */
bool deQueue() {
if (isEmpty()) {
return false;
}
if (head == tail) {
head = -1;
tail = -1;
return true;
}
head = (head + 1) % size;
return true;
}
/** Get the front item from the queue. */
int Front() {
if (isEmpty()) {
return -1;
}
return data[head];
}
/** Get the last item from the queue. */
int Rear() {
if (isEmpty()) {
return -1;
}
return data[tail];
}
/** Checks whether the circular queue is empty or not. */
bool isEmpty() {
return head == -1;
}
/** Checks whether the circular queue is full or not. */
bool isFull() {
return ((tail + 1) % size) == head;
}
};
队列的用法:
#include <iostream>
int main() {
// 1. Initialize a queue.
queue<int> q;
// 2. Push new element.
q.push(5);
q.push(13);
q.push(8);
q.push(6);
// 3. Check if queue is empty.
if (q.empty()) {
cout << "Queue is empty!" << endl;
return 0;
}
// 4. Pop an element.
q.pop();
// 5. Get the first element.
cout << "The first element is: " << q.front() << endl;
// 6. Get the last element.
cout << "The last element is: " << q.back() << endl;
// 7. Get the size of the queue.
cout << "The size is: " << q.size() << endl;
}