数据结构-----队列(顺序队列,循环顺序队列,链队,双端队列)

一、队列:

   简称队,实质是一种操作受限的线性表,其限制为仅允许在表的一端进行插入,在表的另一端进行删除。可以插入的一端是队尾,可以删除的一端是队首。

操作:

    入队、出队。

队列的特点:

    先进先出(FIFO),就如火车过隧道

队列的存储结构:

     队列按存储结构分为顺序队链队

二、顺序队:

      使用数组模拟,队有两个标记,一个标记队首,一个标记队尾。当队首与队尾相等时,表示队空。

      元素入队时,队尾标记后移,队尾位置存入元素,如果是第一个入队的元素,则队首指向该元素所在位置的前一个位置。

      元素出队时,队首标记后移,指向刚出队元素的位置,取出队首所指的元素。

#include<stdio.h>
#include<malloc.h>
# define MaxSize 8

//顺序队
typedef struct{
	int data[MaxSize]; //8
	int front;
	int rear;
}SqQueue; 

//顺序队列判空 
void sqEmpty(SqQueue Sq)
{
	if(Sq.front == Sq.rear)
	{
		printf("队列为空\n");
	}
}

//顺序队列入队
void pushQueue(SqQueue &Sq,int data){
	if(Sq.rear!=MaxSize-1)//队不满 
	{
		Sq.data[++Sq.rear]=data;
		printf("%d入队成功\n",data);
	}
	else
	{
		printf("%d入队失败\n",data);
	}
} 

//顺序队列出队
void popQueue(SqQueue &Sq)
{
	if(Sq.rear==Sq.front)
	{
		printf("队空,元素出队失败\n");
	}
	else
	{
		printf("%d出队成功\n",Sq.data[++Sq.front]);//front++是先赋值,再运算,队首元素出队后,需要后移到下一个元素位置。 
	}
}

void initSqQueue()
{
	SqQueue Sq;
	Sq.front=Sq.rear=-1;//初始化队首队尾指针为-1; 
	sqEmpty(Sq); 
	int elem[5]={5,4,6,4,2};//设置初始化队列元素 
	for(int i=0;i<5;i++)
		pushQueue(Sq,elem[i]);//入队 
	for(int i=0;i<5;i++)
		popQueue(Sq);//出队 
} 

int main()
{
	initSqQueue();//顺序队列 
 } 

 缺点:

        当元素入队后,所有元素出队后,front==rear,队列为空,但是front和rear一直在向数组的后面位置移动,会造成前面空间的浪费,和假溢出的现象(front==rear==MaxSize-1)。于是就有循环队列。

三、循环队列:

        把队列弄成一个环,让front和rear都绕着环走,循环队列是改进的顺序队列。

让front标记执行语句 front=(front+1)%MaxSize,若front初值为0,在一个无限循环中,则front取值为0,1,2,3,4,...  ,MaxSize-1。即以0 ~ MaxSize-1的无限循环数。rear也是如此。

  但是,该循环队列必须留出一个空白空间,因为如果没有空白空间(队满、对空都是:rear == front),则队满和队空状态标记就难以区分了。

状态:

         队满:(queue.rear+1)%MaxSize == queue.front

         队空:queue.rear == queue.front

操作:元素入队、出队时,先移动指针,再取出元素

         入队:queue.rear=(queue.rear+1) % MaxSize; queue.data[queue.rear] = x;

         出队:queue.front= (queue.front+1) % MaxSize; x = queue.data[queue.front];

循环队列中元素个数:

         rear > front :r - f

         rear < front :n - ( f - r )

         综合:(r - f + n)%n

  Coding

#include<stdio.h>
#include<malloc.h>
# define MaxSize 8

//循环队列 
typedef struct{
	int data[MaxSize]; //8
	int front;
	int rear;
}SqQueue; 

//循环队列判空 
void sqEmpty(SqQueue Sq)
{
	if(Sq.rear == Sq.front)
	{
		printf("队列为空\n");
	}
}

//顺序队列入队
void pushQueue(SqQueue &Sq,int data){
	if((Sq.rear + 1)%MaxSize != Sq.front)//队不满才入队 
	{
		Sq.rear = (Sq.rear + 1)%MaxSize; 
		Sq.data[Sq.rear]=data;
		printf("%d入队成功\n",data);
	}
	else
	{
		printf("队满,%d入队失败\n",data);
	}
} 

//顺序队列出队
void popQueue(SqQueue &Sq)
{
	if(Sq.rear==Sq.front)
	{
		printf("队空,元素出队失败\n");
	}
	else
	{
		printf("%d出队成功\n",Sq.data[++Sq.front]);//front++是先赋值,再运算,队首元素出队后,需要后移到下一个元素位置。 
	}
}

//创建循环队列 
void initSqQueue()
{
	SqQueue Sq;
	Sq.front=Sq.rear=-1;//初始化队首队尾指针为-1; 
	sqEmpty(Sq); 
	int elem[5]={5,4,6,4,2};//设置初始化队列元素 
	for(int i=0;i<5;i++)
		pushQueue(Sq,elem[i]);//入队 
	printf("\n"); 
		
	for(int i=0;i<2;i++) //出队2个 
		popQueue(Sq);//出队 
	printf("\n"); 
		
	for(int i=0;i<5;i++)
		pushQueue(Sq,elem[i]);
} 

int main()
{
	initSqQueue();//循环队列 
 } 

四、链队

          采用链式存储结构储存的队列,链队的特点:可以看作是不存在队满状态的队。

          队空状态:lqu ->rear == NULL 或者 lqu -> front == NULL

操作:

          进队:lqu->rear->next=p; lqu->rear=p; 

          出队:p=lqu->front; lqu->front=p->next; x=p->data; free(p);

#include<stdio.h>
#include<malloc.h>

//队结点 
typedef struct Node{
	int data;
	struct Node *next;
}QNode; 

//链队
typedef struct{
	QNode *front;//队头指针 
	QNode *rear; //队尾指针 
}CQueue;


//链队列判空 
void cqEmpty(CQueue *Cq)
{
	if(Cq->front == NULL || Cq->rear == NULL)
	{
		printf("队列为空\n");
	}
}

//链队列入队
void pushChainQueue(CQueue *Cq,int data){
	QNode *temp;
	temp=(QNode *)malloc(sizeof(QNode));
	temp->data=data;
	temp->next=NULL;
	if(Cq->rear==NULL)
	{
		Cq->front=Cq->rear=temp;//队列为空时,刚入队一个元素,队尾、队首都指向进队的第一个元素
		temp->next=NULL;
		printf("%d入队成功\n",data);
	}
	else
	{
		Cq->rear->next=temp;//将元素加入队列 
		Cq->rear=temp;//队尾指向该元素。 
		printf("%d入队成功\n",data);
	} 
} 

//链队出队
void popChainQueue(CQueue *Cq)
{
	QNode *temp;
	if(Cq->front==NULL)
	{
		printf("队空,元素出队失败\n");
	}
	else
	{
		temp=Cq->front;
		printf("%d出队成功\n",temp->data); 
		Cq->front=Cq->front->next;
		free(temp); 
	}
}

//创建链队列 
void initChainQueue()
{
	CQueue *Cq = (CQueue *) malloc(sizeof(CQueue));
	Cq->front=NULL;
	Cq->rear=NULL;
	int elem[5]={5,4,6,4,2};//设置初始化队列元素 
	for(int i=0;i<5;i++)
	{
		pushChainQueue(Cq,elem[i]);	//元素入队 
	} 
	printf("\n");
	for(int i=0;i<6;i++)
	{
		popChainQueue(Cq);	//元素出队 
	} 
	printf("\n");
		
} 

int main()
{
	initChainQueue();//链队列 
 } 

五、双端队列:

           双端队列是一种插入和删除操作在队列两端均可进行的线性表,可以把双端队列看程栈底连在一起的两个栈,设置两个元素end1、end2分别指向队列的两端元素。

           允许在一段进行插入和删除,另一端只允许删除的双端队列称为输入受限的双端队列。

           允许在一段进行插入和删除,另一端只允许插入的双端队列称为输出受限的双端队列。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值