数据结构——栈和队列03

顺序队列的基本操作

前面介绍用两个指针表示队列状态,为区别队空与队满状态,让front指针向前移动一个位置。

顺序结构定义:

typedef strct
{
	datatype data[QUEUE_SIZE];
	int front, rear;
}SeqQueue;

1.置空栈
按队空初始化条件 front = rear =QUEUE_SIZE-1 设置头尾指针。

程序实现:

/*======================================
函数功能:顺序队列置队空
函数输入:队列起始地址
函数输出:无
========================================*/
void initialize_SqQueue(SeqQueue *sq)
{
    sq->front = QUEUE_SIZE-1;
    sq->rear  = QUEUE_SIZE-1;
}

2.判队空
根据对空条件 rear=front, 判断队列是否为空:队空返回1,;队非空返回0。

程序实现:

/*======================================
函数功能:顺序队列判队空
函数输入:队列起始地址
函数输出:1——队空;0——队非空
========================================*/
int  Empty_SqQueue(SeqQueue *sq)
  {  if ( sq->rear == sq->front )  return TRUE;
     else return FALSE;
  } 

3.取队头元素
若队列非空,返回队头元素所在位置下标;否则返回-1.

程序实现:

/*======================================
函数功能:顺序队列取队头元素
函数输入:队列起始地址
函数输出:-1——队空标志;其他值——队头元素位置
========================================*/
int  get_SqQueue(SeqQueue *sq )
{
  if ( ! Empty_SqQueue(sq) )//队非空 
      return (sq->front+1) % QUEUE_SIZE;
  return -1;//队空 
} 

4.入队
若队满,返回FALSE; 否则,队尾指针rear向后移一位,在rear指向处插入入队元素值。

/*======================================
函数功能:顺序队列元素入队
函数输入:队列起始地址,入队元素值
函数输出:0——队满,操作不成功;1——队非满,操作成功
========================================*/
int Insert_SqQueue(SeqQueue*sq, datatype x)
{
	if(sq->front==(sq->rear+1)%QUEUE_SIZE)//判队满
	    return FALSE;
    else
	{
		sq->rear=(sq->rear+1)%QUEUE_SIZE;//队尾指针向后移一位
		sq->data[sq->rear]=x;    //元素x入队
		return TRUE; 
	 } 
}

5.出队
若队非空,头指针front向后移一位,返回front,否则返回队空标记-1。
注意出队操作和取队头元素的区别。

/*======================================
函数功能:顺序队列出队
函数输入:队列起始地址
函数输出:-1——队空标志;其他值——队头元素位置
========================================*/
int Delete_SqQueue(SeqQueue *sq)
{
	if(!Empty_SqQueue(sq))//队非空
	{
		sq->front=(sq->front+1)%QUEUE_SIZE;
		return sq->front;
	 } 
	 return -1;//队空 
}

链队列——问题引入
用循环队列实现杨辉三角形时,若没有队满的限制,将会面临数组溢出问题,这使得计算结果的规模会相应受限。

链队列定义:
用链表表示的队列(队列的链式存储结构),是限制仅在表头删除和表尾插入的单链表

队列的链式存储结构

链队列数据结构设计
链表列由单链表构成,头指针front指向头结点,尾指针rear指向尾指针,头尾指针组合在一个结构中,队列指针 lq 指向此结构。
在这里插入图片描述
1)链结点的数据类型描述

typedef struct node
{
	datatype data;
	struct node *next;
 } LinkListNode;

2)链中头尾指针的数据类型描述

 typedef struct 
 {
 	LinkListNode *front,*rear;
 }LinkQueue;

3)链队列指针 lq 数据类型

LinkQueue *lq;

设置链队列 lq 指针的目的:

讨论:设置lq指针指向链队列头尾指针的组合结构,这样方便队列信息的完整传递。

链队列的基本操作

1.初始化置空队

首次建立只有一个头结点的链队列:
申请一结点;
结点的指针域置空;
队列的头尾指针均指向此结点。
在这里插入图片描述
函数malloc()分配一个大小为LinkListNode字节的空间,并将其首地址放入指针变量lq->front中。

/*======================================
函数功能:链队列初始化
函数输入:队列起始地址
函数输出:无
========================================*/
void initialize_LkQueue(LinkQueue *lq)
{
	lq->front=(LinkListNode *) malloc(sizeof(LinkListNode));
	lq->front->next=NULL;
	lq->rear=lq->front;
}

2.判队空
在这里插入图片描述
若头尾指针相等返回队空标记TRUE;否则返回非空标记FALSE。

/*======================================
函数功能:链队列判队空
函数输入:队列起始地址
函数输出:1——队空;0——队非空
========================================*/
int Empty_LkQueue( LinkQueue *lq )
{    
if  ( lq->front  ==  lq->rear)  return TRUE;
     else   return FALSE;
} 

3.取队头结点

返回是否成功标志,结点值。

若队列非空,取队头指针指向的结点值;
返回操作成功标志TRUE;
否则返回FALSE。

程序实现:

/*======================================
函数功能:链队列取队头结点
函数输入:队列起始地址,(队列结点值)
函数输出:0——队空;1——队非空
========================================*/
int Get_LkQueue(LinkQueue *lq, datatype *x)
{   
 	if ( Empty_LkQueue(lq))  return FALSE;  	//队空
 	x = &(lq->front->next->data);			//取队头结点值
 	return TRUE;
}

4.入队

申请新结点链入队尾;修改队列尾指针;新结点赋值x。
在这里插入图片描述
程序实现:

/*======================================
函数功能:链队列入队
函数输入:队列起始地址,入队列结点值
函数输出:无
========================================*/
void Insert_LkQueue(LinkQueue *lq, datatype x)
{  
  lq->rear->next=(LinkListNode *)malloc(sizeof( LinkListNode )); 
 //新结点链入队尾
 lq->rear=lq->rear->next;	//修改队列尾指针
 lq->rear->data=x; 		//新结点赋值
 lq->rear->next=NULL; 	//尾结点指针域置结束标志NULL
}  

5.出队
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
伪代码描述:

若队列非空,找到队头结点s;
若队列只有一个结点,则队列置空;
摘下队头结点s,修改头结点指针域;
返回s的地址;
返回 NULL;

/*======================================
函数功能:链队列出队
函数输入:队列起始地址
函数输出:队头结点地址
========================================*/
LinkListNode *Delete_LkQueue(LinkQueue *lq) {
	LinkListNode *s;
	if(!Empty_LkQueue(lq)) { //队非空
		s=lq->front->next;//s指向队头结点
		if(s->next==NULL) //队中只有一个结点
			lq->rear=lq->front;//队列置空
		else lq->front->next=s->next;//摘下队头结点
		return(s);           //返回摘下的队头结点地址
	}
	return NULL;             //队空时,返回NULL
}

问题:内存泄漏。

6.销毁链队列
为防止内存泄漏,要做队列的销毁处理。

/*======================================
函数功能:链队列的销毁
函数输入:队列起始地址
函数输出:无
========================================*/
void Destory_LkQueue(LinkQueue *lq)
{
	LinkListNode *s;
	
	while(!Empty_LkQueue(lq))
	{
		s=Delete_LkQueue(lq);
		free(s;)
	}
	free(lq->front);
	lq->front=NULL;
	lq->rear=NULL;
 } 
发布了26 篇原创文章 · 获赞 3 · 访问量 1476

猜你喜欢

转载自blog.csdn.net/herui7322/article/details/104083427