一、队列的定义
这里我用一个生活中的小例子引出队列的定义和一些特点
队列在现实生活中有很多的例子,就比如食堂排队的时候,就是一个典型的队列,而作为排队的人就是队列中的元素,先到食堂窗口的率先买上饭就可以离开了,但是也有一些意外的情况,就比如有一些同学喜欢乱插队,导致后面的同学要多等一个人,也有时呢,前面的某个同学不想吃这家窗口的饭了,然后离开了,在他之后的学生呢,也都会向前一步,还有当饭卖完了,这个窗口排队的人就唉声叹气解散了。
根据例子不难可以发现,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
队列的种类
1.顺序表建立的队列
2.链表建立的队列
3.循环队列
二、队列的特点:
1.仅在表尾进行插入操作,表头进行删除操作的线性表
2.先进先出(FIFO -- First int first out)!
3.插入--> 入队 删除-->出队
三、队列的基本操作
同样跟前面线性表一样,队列呢也有顺序结构和链式结构,在项目或者实例中呢往往用的循环顺序队列比较多。
1.队列结构定义
#define MAXSIZE 100
struct Queue
{
QElemtype *base; //QElemtype 为自定义的数据类型
int front; //用int类型指向队列的头位置
int rear; //指向队列的尾位置
};
注意: 关于队列的溢出问题
1.解决假上溢的方法:
将空间想成一个循环的表,即分配给队列的存储单元可以循环使用,当rear = maxsize,若向量的开端空着,又可以从头使用,当front为maxsize时也同样使用。
引入循环队列
base[0]按在base[maxsize - 1] 之后,若rear+1==M,则令rear=0。利用模(mod,c语言中:%)运算。
添加元素:
Q.base[Q.rear] = x;
Q.rear[Q.rear + 1] % MAXSIZE
删除元素:
x = Q.base[Q.front]
Q.front = (Q.front + 1)%MAXSIZE
2.初始化
//顺序表
void Init()
{
base = new QElemtype[MAXSIZE];
rear = front = 0;
}
//链式
void Init()
{
front = rear = new Qnode[MAXSIZE];
if(!front)
cout <<"初始化失败";exit(0);
front->next = nullptr;
}
3.销毁队列
void release()
{
delete []base;
}
4.入队列
void Enqueue(QElemtype e)
{
if(IsFull())
cout <<"queue have been fulled"<<endl;
this->base[rear] = e;
rear = (rear+1)%MAXSIZE;
}
5.出队列
void Dequeue(QElemtype &e)
{
if(IsEmpty())
cout <<"the queue haven't data"<<endl;
e = base[front];
front = (front+1)%MAXSIZE;
}
还有一些比较简单的操作,例如判断队列是否为空,是否为满,获取队列头元素。这些方法我写到总汇里面(第四部分)里面去了。
四、代码整合
在实例中用C++类模板的方法整合所有代码,可以调用类直接使用类的接口函数。
1
、顺序结构
#ifndef QUEUE_H_
#define QUEUE_H_
#define MAXSIZE 5
#include<cstdlib>
#include<iostream>
using std::cout;
using std::endl;
template<class T>
class Queue
{
private:
T* base;
int front;
int rear;
public:
Queue();
~Queue();
bool IsEmpty();
bool IsFull();
void Enqueue(T e);
void Dequeue(T &e);
T GetHead();
};
template<class T>
Queue<T>::Queue()
{
this->base = new T[MAXSIZE];
front = rear = 0;
}
template<class T>
Queue<T>::~Queue()
{
delete []base;
}
template<class T>
bool Queue<T>::IsEmpty()
{
if(rear == front)
return true;
else
return false;
}
template<class T>
bool Queue<T>::IsFull()
{
if((rear+1)%MAXSIZE == front)
return true;
else
return false;
}
template<class T>
void Queue<T>::Enqueue(T e)
{
if(IsFull())
cout << "queue have been fulled"<<endl;
this->base[rear] = e;
rear = (rear+1)%MAXSIZE;
}
template<class T>
void Queue<T>::Dequeue(T &e)
{
if(IsEmpty())
cout <<"the queue haven't data"<<endl;
e = base[front];
front = (front+1)%MAXSIZE;
}
template<class T>
T Queue<T>::GetHead()
{
if(front != rear)
return base[front];
}
#endif
二、链式结构
#ifndef QUEUE_H_
#define QUEUE_H_
#define MAXSIZE 100
#include<cstdlib>
typedef int Elemtype;
struct Qnode
{
Elemtype data;
struct Qnode* next;
};
typedef struct Qnode* LinkQueue;
template<class T>
class Queue
{
private:
LinkQueue front;
LinkQueue rear;
public:
Queue();
~Queue();
void Enqueue(T e);
void Dequeue(T &e);
void GetHead(T &e);
};
template<class T>
Queue<T>::Queue()
{
front = rear = new Qnode[MAXSIZE];
if(!front)
exit(0);
front->next = nullptr;
}
template<class T>
Queue<T>::~Queue()
{
while(front)
{
LinkQueue p = front->next;
delete front;
front = p;
}
}
template<class T>
void Queue<T>::Enqueue(T e)
{
LinkQueue p = new Qnode[MAXSIZE];
if(!p)
exit(0);
p->data = e;
p->next = nullptr;
rear->next = p;
rear = p;
}
template<class T>
void Queue<T>::Dequeue(T &e)
{
if(front == rear)
exit(0);
LinkQueue p = front->next;
e = p->data;
front->next = p->next;
delete p;
}
template<class T>
void Queue<T>::GetHead(T &e)
{
e = front->next->data;
}
#endif
五、总结
队列这部分更新完了,纯手敲,后面继续写其他的数据结构。