数据结构5--队列

队列模型

  • 队列:只允许在一端进行插入操作,而另一端进行删除操作的线性表
  • 允许插入(入队,进队)的一端称为队尾,允许删除(出队)的一端称为队头
  • 空队列:不含任何数据元素的队列。.

在这里插入图片描述

操作特性:先进先出

队列的顺序存储

入队

  • 首先 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;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一记绝尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值