注意:取余符号 % 的意思
% 除数小于被除数,结果就是除数
除数大于等于被除数,结果就是余数
1. 什么是队列
队列(Queue):具有一定操作约束的线性表
队头与队尾: 允许元素插入的一端称为队尾,允许元素删除的一端称为队头。
插入和删除操作:只能在一端(front)插入,而在另一端(rear)删除
数据插入:入队列(AddQ)
数据删除:出队列(DeleteQ)
先进先出:FIFO
特点:1.队列中的数据元素遵循“先进先出”(First In First Out)的原则,简称FIFO结构。
2.在队尾添加元素,在队头删除元素。
2. 队列的顺序存储结构实现(★★★★★★★有图★★★★★★★)
2.1 模板
C++
begin:队首标志 end:队尾标志 capacity:数组容量 queue:数组
template <typename T>
class LoopQueue
{
public:
LoopQueue(int c = 10);
~LoopQueue();
public:
bool isEmpty(); //队列的判空
int size(); //队列的大小
bool push(T t); //入队列
bool pop(); //出队列
T front(); //队首元素
private:
int capacity;
int begin;
int end;
T* queue;
};
C
类型名称:队列(Queue)
数据对象集:一个有 0 个或多个元素的有穷线性表
操作集:长度为 MaxSize 的队列 Q∈Queue,队列元素 item∈ElementType
队列的基本操作主要有:
#include<stdio.h>
#include<malloc.h>
#define MaxSize 100
typedef int ElementType;
typedef struct QNode *Queue;
struct QNode{
ElementType Data[MaxSize];
int front; // 记录队头
int rear; // 记录队尾
};
Queue CreateQueue(int MaxSize):生成长度为 MaxSize 的空队列
int IsFull(Queue Q):判断队列 Q 是已满
void AddQ(Queue Q,ElementType item):将数据元素 item 插入队列 Q 中
int IsEmpty(Queue Q):判断队列 Q 是否为空
ElementType DeleteQ(Queue Q):将队头数据元素从队列中删除并返回
2.2 初始化构造
C++
template<typename T>
LoopQueue<T>::LoopQueue(int c = 10)
:
{
capacity = c;
begin = 0;
end = 0;
queue = new T[capacity];
queue(nullptr)
};
C
// 初始化
Queue CreateQueue(){
Queue Q;
Q = (Queue)malloc(sizeof(struct QNode));
Q->front = -1;
Q->rear = -1;
return Q;
}
2.3 析构函数
C++
template<typename T>
LoopQueue<T>::~LoopQueue()
{
delete[]queue;
}
2.4 判断是否为空
C++
template <typename T>
bool LoopQueue<T>::isEmpty()
{
if (begin == end)
return true;
return false;
};
C
//判断队列是否为空
int IsEmpty(Queue Q){
return (Q->front == Q->rear);
}
2.5 判断队列是否已满
C++
template <typename T>
bool LoopQueue<T>::pop()
{
if (end == begin) //判断队列是否为空
{
return false;
}
begin = (begin + 1) % capacity;
return true;
};
C
// 判断队列是否已满
int IsFull(Queue Q){
return ((Q->rear+1) % MaxSize == Q->front);
}
2.6 入队
添加元素时,元素只能从队尾一端进入队列,也即是2只能跟在1后面,3只能跟在2后面。
C++
template<typename T>
bool LoopQueue<T>::push(T t)
{
if (end + 1 % capacity == begin) //判断队列是否已满 end + 1 % capacity == begin ,end + 1 % capacity余数是否为零?
{
return false;
}
queue[end] = t;
end = (end + 1) % capacity;
return true;
};
C
// 入队
void AddQ(Queue Q,ElementType item){
if(IsFull(Q)){
printf("队列满");
return;
}else{
Q->rear = (Q->rear+1) % MaxSize; //(Q->rear+1) % MaxSize =Q->rear+1 ,只要小于MaxSize ,那么结果还是rear+1 !!!!!!
Q->Data[Q->rear] = item;
}
}
2.7 出队
元素只能从队首出队列,出队列的顺序为:1、2、3,与入队时的顺序一致,这就是所谓的“先进先出”。
C++
template <typename T>
bool LoopQueue<T>::pop()
{
if (end == begin) //判断队列是否为空
{
return false;
}
begin = (begin + 1) % capacity;
return true;
};
C
// 出队
ElementType DeleteQ(Queue Q){
if(IsEmpty(Q)){
printf("队列空");
return 0;
}else{
Q->front = (Q->front+1) % MaxSize;
return Q->Data[Q->front];
}
}
2.8 测试
C
int main(){
Queue Q;
Q = CreateQueue();
AddQ(Q,3);
printf("3入队\n");
AddQ(Q,5);
printf("5入队\n");
AddQ(Q,11);
printf("11入队\n");
printf("%d出队\n",DeleteQ(Q));
printf("%d出队\n",DeleteQ(Q));
return 0;
}
C++
int main()
{
LoopQueue<string> queue(6);
queue.push("one");
queue.push("two");
queue.push("three");
queue.push("four");
queue.push("five");
cout << "队列长度" << queue.size() << endl;
while (!queue.isEmpty())
{
cout << queue.front() << endl;
queue.pop();
}
getchar();
return 0;
}
3. 队列的链式存储结构实现
队列为空的时候,front和rear指针都指向头结点
队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行,front 在链表头,rear 在链表尾,从 rear 入队,从 front 出队
队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行,front 在链表头,rear 在链表尾,从 rear 入队,从 front 出队
3.1 模板
C++
template<typename T>
struct Node
{
Node(T t) :value(t), next(nullptr){}
Node() = default;
T value; //vaule : 链表节点的值
Node<T> * next; //next : 指针,指向下一个节点
}
template<typename T>
class LinkQueue
{
public:
LinkQueue();
~LinkQueue();
bool isEmpty();
int size();
bool pop();
void push(T t);
T front();
private:
Node<T>* phead;
Node<T>* pend;
int count;
};
C
#include<stdio.h>
#include<malloc.h>
typedef int ElementType;
typedef struct QNode *Queue;
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{
struct Node *rear; // 指向队尾结点
struct Node *front; // 指向队头结点 ?????????????????????????????????????????????????
};
Queue CreateQueue(); // 初始化队列
void AddQ(Queue Q,ElementType item); // 入队
ElementType DeleteQ(Queue Q); // 出队
int IsEmpty(Queue Q); // 判断队列是否为空
3.2 初始化构造
C++
template<typename T>
LinkQueue<T>::LinkQueue()
:phead(nullptr),pend(nullptr),count(0)
{
phead = new Node<T>();
pend = phead;
count = 0;
};
C
// 初始化
Queue CreateQueue(){
Queue Q;
Q = (Queue)malloc(sizeof(struct QNode));
Q->front = NULL;
Q->rear = NULL;
return Q;
}
3.3 析构函数
template <typename T>
LinkQueue<T>::~LinkQueue()
{
while (phead->next != nullptr)
{
Node<T> * pnode = phead;
phead = phead->next;
}
};
3.4 判断是否为空
C++
template <typename T>
bool LinkQueue<T>:: isEmpty()
{
return count==0;
};
C
// 是否为空
int IsEmpty(Queue Q){
return (Q->front == NULL && Q->rear== NULL);
}
3.5 队列大小
C++
template <typename T>
int LinkQueue<T>::size()
{
return count;
};
3.6 入队 (队列为空的时候,front=rear=NULL)
C++
//在队尾插入
template <typename T>
void LinkQueue<T>::push(T t)
{
Node<T>* pnode = new Node<T>(t); //创建一个结点
pend->next = pnode; //将原来的尾指针指向它
pend = pnode; //将它更新成尾结点
count++; //计数器加一
};
C
// 入队
void AddQ(Queue Q,ElementType item){
struct Node *node;
node = (struct Node *)malloc(sizeof(struct Node));
node->Data = item;
node->Next = NULL;
if(Q->rear==NULL){ //此时队列空
Q->rear = node;
Q->front->next = node;
}else{ //不为空
Q->rear->Next = node; // 将结点入队
Q->rear = node; // rear 仍然保持最后
}
}
3.7 出队
C++
//在队首弹出
template <typename T>
bool LinkQueue<T>::pop()
{
if (count == 0)
return false;
Node<T>* pnode = phead->next;
phead->next = phead->next->next; //将第二个结点变成第一个,原来第一个删除掉
delete pnode;
count--;
return true;
};
C
// 出队
ElementType DeleteQ(Queue Q){
struct Node *FrontCell;
ElementType FrontElem;
if(IsEmpty(Q)){
printf("队列空");
return 0;
}//_______________________________________已经修改_________________________________
FrontCell = Q->front->next; //找到第一个元素结点 ???????????????????????????????????????
if(Q->front->next == Q->rear){ // 队列中只有一个元素 ,因为已经排除队列为空的情况了
Q->front = Q->rear = NULL;
}else{
Q->front->next = Q->front->Next->next;
}
FrontElem = FrontCell->Data;
free(FrontCell);
return FrontElem;
}
3.8 测试
C++
int _tmain(int argc, _TCHAR* argv[])
{
LinkQueue<string> lqueue;
lqueue.push("one");
lqueue.push("two");
lqueue.push("three");
lqueue.push("four");
lqueue.push("five");
cout << "队列的大小" << lqueue.size() << endl;
while (!lqueue.isEmpty())
{
cout << lqueue.front() << endl;
lqueue.pop();
}
getchar();
return 0;
}
C
int main(){
Queue Q;
Q = CreateQueue();
printf("入队5\n");
AddQ(Q,5);
printf("入队4\n");
AddQ(Q,4);
printf("入队4\n");
AddQ(Q,3);
printf("出队%d\n",DeleteQ(Q));
printf("出队%d\n",DeleteQ(Q));
printf("出队%d\n",DeleteQ(Q));
printf("%d\n",DeleteQ(Q));
return 0;
}