【数据结构】队列

队列

  • 队列(Queue):插入在表一端进行,删除在表的另一端进行的线性表。
  • 队尾(rear):允许插入的一端
  • 队头(front):允许删除的一端
  • 空队:不含数据元素的队列
  • 入队(In):插入元素
  • 出队(Out):删除元素
    特点:先进先出(FIFO)

顺序队

思考

如何改造数组实现队列的顺序存储?

答:设置对头、队尾两个指针。约定:front指向队头的前一个位置,rear指向对尾。

描述顺序队需要几个属性?

  • 存储空间的起始位置:data
  • 存储容量:MaxSize
  • 当前队尾的位置:rear
  • 当前队头的位置:front

说明

1、

若 把顺序队列定义为:SeQueue *sq;
则 申请顺序队存储空间:sq = new SeQueue;
队列的数据区:sq->data[0]…sq->data[MaxSize - 1]
队尾元素表示为:sq->data[sq->rear]
队头元素表示为:sq->data[sq->front + 1]

2、队头、队尾与队中元素的关系;

入队:队尾指针加1 sq->rear++;
出队:队头指针加1 sq->front++
队空条件:sq->rear = = sq->front
队满条件:sq->rear = = MaxSize - 1

假溢现象

当顺序队一直入队,再出队,再有元素插入时,就会被插入数组下标最大的位置上之后,队列的空间用完,此时数组的低端还要空闲空间,这就出现了假溢现象。
假溢现象

如何解决假溢现象?

将队列数据区data[0]…data[MaxSize - 1]看成头尾相接的循环结构,头尾指针关系不变——循环队列
不存在物理的循环结构,用软件方法实现。
求模:((MaxSize - 1) + 1) % MaSize == 0

循环队列

入队:rear = (rear + 1) % MaxSize
出队:front = (front + 1) % MaxSize
队空条件:front = rear ➡num = 0;
队满条件:(rear + 1) % MaxSize = front ➡ num =MaxSize

循环队列基本操作

循环队列数据类型定义

typedef struct{
	DataType data[MaxSize];
	int front, rear;
	int num;
}C_SeQueue;

循环队列初始化

C_SeQueue *Init_C_SeQueue()
{
	C_SeQueue *q;
	q = new C_SeQueue;
	q->rear = 0;
	q->front = 0;
	return q;
}

循环队列判断队空

int Empty_SeQueue(C_SeQueue *q)
{
	if(q->rear == q->front)
		return 1;
	else
		return 0;
}

循环队列判断队满

int Full_C_SeQueue(C_SeQueue *q)
{
	if((q->rear + 1) % MaxSize == q->front)
		return 1;
	else
		return 0;
}

循环队列插入算法

int In_C_SeQueue(C_SeQueue *q, DataType x)
{
	if(Full_C_SeQueue(q))
		return 0;
	else
	{
		q->rear = (q->rear + 1) % MaxSize;
		q->data[q->rear] = x;
		return 1;
	}
}

循环队列出队算法

int Out_C_SeQueue(C_SeQueue *q, DataType *x)
{
	if(Empty_C_SeQueue(q))
		return 0;
	else
	{
		x = q->data[q->rear];
		q->front = (q->front + 1) % MaxSize;
		return 1;
	}
}

链队

从结构上考虑,将队头、队尾指针封装在一个结构体中.
表头作为队头,表尾作为队尾。
习惯采用带头结点的形式。

链队的结构体

typedef struct{
	DataType data;
	struct node *next;
}QNode;

typedef struct{
	QNode *front,*rear;
}LQueue;

链队的初始化

LQuquq *Init_LQueue(){
	LQueue *q;
	QNode *p;
	q = new LQueue;
	p = new QNode;
	q->front = q->rear = p;
	p->next = NULL;
	return q;
}

链队入队算法

void In_LQueue(LQueue *q,DataType x)
{
	Qnode *p;
	p = new QNode;
	p->data = x;
	p->next = NULL;
	q->rear->next = p;    //将新结点插入队尾
	q-rear = p;           //队尾指针指向新结点
}

链队的删除算法

int Out_LQueue(LQueue *q, DataType *x)
{
	QNode *p;
	if(Empty_LQueue(q))
		return 0;
	else
	{
		p = q->front->next;
		q->front->next = p->next;
		x = p->data;
		delete(p);
		if(q->front->next == NULL)  //若队列中只有一个元素时,出队后表为空
			q->rear = q->front;
		return 1;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值