队列模型
- 队列:只允许在一端进行插入操作,而另一端进行删除操作的线性表
- 允许插入(入队,进队)的一端称为队尾,允许删除(出队)的一端称为队头
- 空队列:不含任何数据元素的队列。.
操作特性:先进先出
队列的顺序存储
入队:
-
首先 rear 指向队尾的位置(下标为0的位置),然后 a1 入队,存储在 rear 所指的单元
-
然后 rear 向后移动一个单元,再让第二个元素(a2) 入队
-
以此类推
出队:
- 从队头开始操作,a1 出队,后面的元素向前移动补位,依次出队
顺序存储的改进
入队:
-
设置队头队尾两个指针,front 和 rear 都为 -1
-
当有数据要入队时,让 rear 先 +1,rear 指向下标为0处,然后将数据存储在 rear 处
-
rear 再 +1 ,继续入队,
-
队头指针 front 指向队头元素的前一个位置,
-
队尾指针 rear 指向队尾元素。
-
特点:从队尾依次入队,从队头依次出队。
出队:
- 首先 front +1,移动到下一个单元,此时 front 为0, 然后将 front 所在的单元的数据取出
- 然后 front 再 +1,front 所在的位置的元素被取出
此时如果继续入队的话,会出现假溢出
假溢出:当元素被插入到数组中下标最大的位置上之后,队列的空间就用尽了,尽管此时数组的低端还有空闲空间,这种现象叫做假溢出。
解决假溢出: 将存储队列的数组首尾相接
实现循环队列
不存在物理的循环结构,用软件方法实现
求模:(4+1)mod 5 = 0
队列的主要操作
判断循环队列是否为空
front == rare
判断循环队列是否满
front == rare
将队空和队满的判定条件分开
- 附设一个存储队列中元素个数的变量 num, 当 num = 0 时队空,当 num = QueueSize 时为队满
- 修改队满条件,浪费一个元素空间,队满时数组中只有一个空闲单元
- 设置标志 flag ,当 front = rear 且 flag = 0 时为队空,当 front = rear 且 flag =1 时为队满
循环队列的定义(C++)
const int QUEUESIZE = 100; // 定义队列的最大长度
class CirQueue
{
private:
DataType * data; // 指向队列存储空间
int front; // 队首下标
int rear; // 队尾下标
int mSize; // 存放队列的数组的大小
public:
CirQueue(); // 建立缺省长度(QUEUESIZE)的队列
CirQueue(); // 建立长度为size 的队列
~CirQueue(); // 清空队列,释放内存
bool enQueue(DataType item); // 入队
bool deQueue(DataType item); //出队
bool getFront(Data Type *item); //读取队头元素,但不删除
bool isEmpty(); //判断队列是否为空
bool isFull(); //判断队列是否为满
void clearQueue(); //清空队列
void displayQueue(); //显示队列内容
int queueLength(); //获取队列元素个数
};
循环队列的定义(C语言)
#define QUEUESIZE = 100; // 定义队列的最大长度
typedef struct
{
DataType * data; // 指向队列存储空间
int front; // 队首下标
int rear; // 队尾下标
int mSize; // 存放队列的数组的大小
}Queue;
initCirQueue(Queue &q); // 建立缺省长度(QUEUESIZE)的队列
destroyCirQueue(Queue &q); // 建立长度为size 的队列
bool enQueue(Queue &q,DataType item); // 入队
bool deQueue(Queue &q,DataType &item); //出队
bool getFront(Queue q,DataType &item); //读取队头元素,但不删除
bool isEmpty(Queue q); //判断队列是否为空
bool isFull(Queue q); //判断队列是否为满
void clearQueue(Queue &q); //清空队列
void displayQueue(Queue q); //显示队列内容
int queueLength(Queue q); //获取队列元素个数
循环队列的实现
入队
bool CirQueue::enQueue(DataType x)
{
if(isFull())
return false;
rear = (rear+1) % QUEUESIZE;
data[rear] = x;
return true;
}
出队
bool CirQueue::deQueue(DataType * item)
{
if(isEmpty())
return false;
front = (front+1)%QUEUESIZE;
*item = data[front];
return true;
}
循环队列
#include <stdio.h>
#include <malloc.h>
// 循环队列
typedef struct Queue
{
int* pBase; // 数组首地址
int front;
int rear;
}QUEUE;
void init(QUEUE*); // 初始化
bool enQueue(QUEUE*, int); //入队: 哪个队列,放什么值
void traverseQueue(QUEUE*);
bool full_queue(QUEUE*);
bool out_queue(QUEUE*, int*);
bool empty_queue(QUEUE*);
int main(void)
{
QUEUE Q;
int val;
init(&Q);
enQueue(&Q, 1);
enQueue(&Q, 2);
enQueue(&Q, 3);
enQueue(&Q, 4);
enQueue(&Q, 5);
enQueue(&Q, 6);
traverseQueue(&Q);
if (out_queue(&Q, &val))
printf("\n出队元素:%d\n", val);
else
printf("fail");
traverseQueue(&Q);
return 0;
}
//队列初始化,创建一个队
void init(QUEUE* pQ)
{
pQ->pBase = (int*)malloc(sizeof(int) * 6);
pQ->front = 0;
pQ->rear = 0;
}
//判断队是否满
bool full_queue(QUEUE* pQ)
{
if ((pQ->rear + 1) % 6 == pQ->front) // 循环队列
return true;
else
return false;
}
// 入队
bool enQueue(QUEUE * pQ, int val)
{
if (full_queue(pQ))
return false;
else
{
pQ->pBase[pQ->rear] = val; // 从队尾入队
pQ->rear = (pQ->rear + 1) % 6;
return true;
}
}
// 遍历
void traverseQueue(QUEUE* pQ)
{
int i = pQ->front;
while (i != pQ->rear)
{
printf("%d\t", pQ->pBase[i]);
i = (i + 1) % 6;
}
return;
}
// 判断队是否为空
bool empty_queue(QUEUE* pQ)
{
if (pQ->front == pQ->rear)
return true;
else
return false;
}
// 出队
bool out_queue(QUEUE*pQ, int*pVal)
{
if (empty_queue(pQ))
return false;
else
{
*pVal = pQ->pBase[pQ->front];
pQ->front = (pQ->front + 1) % 6;
return true;
}
}
优先队列
普通的队列是一种先进先出的数据结构,元素在队尾追加,从队头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。
优先队列具有最高优先级先出的行为特征,优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有:
- 查找
- 删除
- 插入一个新元素
在最小优先队列中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。优先权队列中的元素可以有相同的优先权,查找与删除操作可以可根据任意优先级进行。
C++优先队列类似队列,但是在这个数据结构中的元素按照一定的断言排列有序。
- empty(); 如果优先队列为空,则返回真
- pop(); 删除第一个元素
- push(); 加入一个元素
- size(); 返回优先队列中拥有的元素个数
- top(). 返回优先队列中优先级最高的元素
优先队列:
priority_queue<int , vector<int>, cmp> que;
其中,第一个参数为数据类型,第二个参数为容器类型,第三个参数为比较函数。后两个参数根据需要可以省略。
优先队列最常用的用法:
priority_queue<int>que; //参数为数据类型,默认优先级(最大值优先)构造队列
如果要从小到大输出,有四种办法:
- 使用C++自带的库函数
- 自定义优先级1
- 自定义优先级2
- 自定义优先级3
如何控制优先队列的优先级?
方法1: 使用C++自带的库函数
首先在头文件中引用库函数
#include<functional>
functional提供了如下的基于模板的比较函数对象。
- equal_to:等于
- not_equal_to :不等于
- greater:大于
- greater_equal:大于等于
- less:小于
- less_equal :小于等于
创建优先队列:
priority_queue<int, vector<int>, less<int> >que1; //最大值优先
priority_queue<int , vector<int>,greater<int> >que2; // 最小值优先
方法2: 自定义优先级1,队列元素为数值型
struct cmp1
{
bool operator() (int a,int b)
{
return a<b; // 最大值优先
}
};
struct cmp2
{
bool operator() (int a,int b)
{
return a>b; // 最小值优先
}
};
创建优先队列:
priority_queue<int , vector<int>, cmp1> que3;
最大值优先
priority_queue<int , vector<int>, cmp2> que4;
最小值优先
方法3: 自定义优先级2,队列元素为结构体类型
struct node1
{
int x,y; // 结构体中的成员
bool operator< (const node1 &a)const
{
return x < a.x; // 最大值优先
}
};
struct node2
{
int x,y; // 结构体中的成员
bool operator< (const node2 &a)const
{
return x > a.x; // 最小值优先
}
};
创建优先队列:
priority_queue<node1>que5;
// 使用时要把数据定义为 node1 类型
priority_queue<node2>que6;
// 使用时要把数据定义为 node2 类型
方法4 自定义优先级 3,队列元素为结构体类型
struct node3
{
int x ,y;
};
bool operator<(const node3 &a, const node3 &b) //在结构体外面定义
{
return a.x < b.x; // 按成员 x 最大值优先
}
struct node4
{
int x ,y;
};
bool operator<(const node4 &a, const node4 &b) //在结构体外面定义
{
return a.x > b.x; // 按成员 x 最小值优先
}
priority_queue<node3>que7;
// 使用时要把数据定义为 node3 类型
priority_queue<node4>que8;
// 使用时要把数据定义为 node4 类型
代码
#include <iostream>
#include <functional>
#include <queue>
#include <vector>
using namespace std;
//自定义优先级1,队列元素为数值型
struct cmp1
{
bool operator() (int a, int b)
{
return a < b; // 最大值优先
}
};
struct cmp2
{
bool operator() (int a, int b)
{
return a > b; // 最小值优先
}
};
//自定义优先级2,结构体类型
struct node1
{
int x, y;// 结构体中的成员
node1() {};// 默认构造
node1(int _x,int _y) // 为方便赋值,采用构造函数
{
x = _x;
y = _y;
}
bool operator < (const node1& a)const
{
return x < a.x; // 按成员x 的最大值优先
}
};
struct node2
{
int x, y;
node2() {};
node2(int _x, int _y)
{
x = _x;
y = _y;
}
bool operator < (const node2 & a)const
{
return x > a.x; // 按成员x 的最小值优先
}
};
// 自定义优先级3 结构体类型
struct node3
{
int x, y;
node3() {};
node3(int _x,int _y)
{
x = _x;
y = _y;
}
};
bool operator < (const node3& a, const node3& b)
{
return a.x < b.x; // 按成员x 的最大值优先
}
struct node4
{
int x, y;
node4() {};
node4(int _x, int _y)
{
x = _x;
y = _y;
}
};
bool operator < (const node4& a, const node4& b)
{
return a.y > b.y; // 按成员y 的最小值优先
}
int a[] = { 15,7,32,26,97,48,36,89,6,49,67,0 };
int b[] = { 1,2,5,6,9,8,6,9,7,19,27,0 };
int main()
{
priority_queue<int>que; //采用默认优先级构造队列
//使用 C++ 自带的库函数<functional>
priority_queue<int, vector<int>, less<int> >que1; // 最大值优先
priority_queue<int, vector<int>, greater<int> >que2; //最小值优先
// 自定义优先级1
priority_queue<int, vector<int>, cmp1>que3;
priority_queue<int, vector<int>, cmp2>que4;
//自定义优先级2
priority_queue<node1>que5;
priority_queue<node2>que6;
//自定义优先级3
priority_queue<node3>que7;
priority_queue<node4>que8;
for (int i = 0; a[i]; i++) // a[i] 为0时停止,数组最后一个数为0
{
que.push(a[i]);
que1.push(a[i]);
que2.push(a[i]);
que3.push(a[i]);
que4.push(a[i]);
}
for (int i = 0; a[i] && b[i]; i++)//a[i]或 b[i]为0时停止
{
que5.push(node1(a[i], b[i]));
que6.push(node2(a[i], b[i]));
que7.push(node3(a[i], b[i]));
que8.push(node4(a[i], b[i]));
}
cout << "采用默认优先级:" << endl;
cout << "Queue 0: " << endl;
while (!que.empty())
{
cout << que.top() << " ";
que.pop();
}
cout << endl << endl;
cout << "采用头文件 functional 定义优先级:" << endl;
cout << "Queue 1: " << endl;
while (!que1.empty())
{
cout << que1.top() << " ";
que1.pop();
}
cout << endl;
cout << "Queue 2: " << endl;
while (!que2.empty())
{
cout << que2.top() << " ";
que2.pop();
}
cout << endl << endl;
cout << "采用自定义优先级方式1:" << endl;
cout << "Queue 3: " << endl;
while (!que3.empty())
{
cout << que3.top() << " ";
que3.pop();
}
cout << endl;
cout << "Queue 4: " << endl;
while (!que4.empty())
{
cout << que4.top() << " ";
que4.pop();
}
cout << endl << endl;
cout << "采用自定义优先级方式2:" << endl;
cout << "Queue 5: " << endl;
while (!que5.empty())
{
cout << que5.top().x << " ";
que5.pop();
}
cout << endl;
cout << "Queue 6: " << endl;
while (!que6.empty())
{
cout << que6.top().x << " ";
que6.pop();
}
cout << endl << endl;
cout << "采用自定义优先级方式3:" << endl;
cout << "Queue 7: " << endl;
while (!que7.empty())
{
cout << que7.top().x << " ";
que7.pop();
}
cout << endl;
cout << "Queue 8: " << endl;
while (!que8.empty())
{
cout << que8.top().y << " ";
que8.pop();
}
cout << endl << endl;
return 0;
}