数据结构--队列

1.定义:队列是限定只能在表的一端进行插入,在表的另一端进行删除的线性表。

允许插入的一端-----队尾(rear),允许删除的一端----队头(front)。

2.特点:先进先出(FIFO)


3.链队列

用链表表示的队列

//LsQueue.h

#include "iostream"
typedef int ElemType;
struct quenode        //链队列结点的结构描述
{
 ElemType data;
 quenode *next;
};
                                    
class LsQueue
{
private:
 quenode *front,*rear;
public:
    LsQueue();
 ~LsQueue();
 int  IsEmpty();
 void Display();
 void AddQ(ElemType x);
 ElemType DelQ();
 ElemType GetFront();
};

空的链队列的判决条件:Q.front==Q.rear,头指针、尾指针均指向头结点。

入队操作

链队列的基本操作

//初始化一个空的链队列

int InitQueue( LinkQueue * Q ) {
   Q->front=Q->rear=( )malloc(sizeof( ) );
   if(! Q->front)   return FALSE;
   Q->front->next=NULL;
   return TRUE;
}

//销毁队列

int  DestroyQue(LinkQueue * Q) {
   while(Q->front) {
      Q->rear=(Q->front)->next;
      free(Q->front);
      Q->front=Q->rear;
   }
   return TRUE;
}

//插入元素e为新的队尾元素

int EnterQueue(LinkQueue *Q,QElemType e) {
   p=( )malloc(sizeof(LinkQueueNode));
   if(! p)   return FALSE;
   p->data=e;    p->next=NULL;
   Q->rear->next=p;    
   Q->rear=p;
   return TRUE;
}

//删除队列的队头元素,以e返回

int DeleteQueue(LinkQueue *Q,ElemType *e) {
    if(Q->front==Q->rear) return FALSE;
    p=Q->front->next; *e=p->data;
    Q->front->next=p->next;
    if(Q->rear==p)  Q->rear=Q->front ;
    free(p);
    return TRUE;
}

//LsQueue.cpp

#include "LsQueue.h"
#include "iostream"

using namespace std;

LsQueue::LsQueue()         //构造函数,初始化一个空队列
{
	quenode *p;
	p=new quenode;
	p->next=NULL;
	front=rear=p;
}
int LsQueue::IsEmpty()     //判断队列是否为空
{
	if (front==rear)
		return 1;
	else
		return 0;
}

ElemType LsQueue::GetFront()   //取队首元素,不出队
{
	ElemType x;quenode *p;
	if (front==rear)
	{
		cout<<"\n Queu Is Empty!"<<endl;
		x=-1;
	}
	else
	{
		p=front->next;
		x=p->data;
	}
	return x;
}

void LsQueue::AddQ(ElemType x)         //值为x的结点入队
{
	quenode *s;
	s=new quenode;
	s->data=x;
	s->next=NULL;
	rear->next=s;
	rear=s;
}

ElemType LsQueue::DelQ()        //出队一个元素
{
	ElemType x;quenode *p;
	if (front==rear)
	{
		cout<<"\n 队列为空。"<<endl;
		x=-1;
	}
	else{
		p=front->next;    //p指向第一个数据结点
		front->next=p->next;
		if (p->next==NULL) rear=front;  //防止尾指针丢失
	    x=p->data;
		delete p;
	}
	return x;
}


4.循环队列

引出:设顺序队列的预定义长度为M,则:

         当front=0,rear=M时,再有元素入队发生溢出----真溢出

         当front≠0,rear=M时,再有元素入队发生溢出----假溢出

解决方案:

有如下两种方法:

1)采用平移元素的方法。一旦发生“假溢出”,就把整个队列的元素平移到存储区的首部。显然平移元素的方法效率是很低的。

 2)将整个队列作为循环队列来处理:把队列想成环形,让sq[0]接在sq[M-1]之后,若++rear==M,则令rear=0;

利用“模”运算

入队:rear=(rear+1)%M

出队:front=(front+1)%M

然而会出现新的问题,队空:front == rear

                                        队满:front == rear,如下图所示:

故提出以下解决问题的方案:

(1)另外设一个标志flag以区别队空与队满条件:

当front==rear且flag=0时为队空,当front==rear且flag=1时为队满。

(2)设记录实际队列元素个数的数据成员来区别

(3)牺牲一个队列元素空间以区别队空与队满条件

          队空:front==rear

          队满:(rear+1)%M==front

即拥有MAXSIZE个数组元素的数组仅能表示一个长度为MAXSIZE-1的循环队列。

程序实现

//SeQueue.h

//************顺序栈类定义*************
typedef int ElemType;                  //数据元素的类型
const int MAXSIZE=100;                 //数组的容量

class SeQueue 
#include "SeQueue.h"
#include "iostream"

using namespace std;

int SeQueue::Empty()                     //判断循环队列是否为空
{
	if (rear==front)
		return 1;
	else  
		return 0;
}

void SeQueue::Display()                  //输出队列
{
	int k;
	if (front==rear)
		cout<<"\n  Queue is Empty!"<<endl;
	else
	{for(k=front;k <= rear;k=(k+1)%MAXSIZE)	cout<<elem[k];
	
	}

}


ElemType SeQueue::GetFront()              //取队列队首元素,不出队
{
	ElemType x;
	if (front==rear){
		cout<<"\n Queu is Empty!"<<endl;
		x=-1;
	}
	else 
		x=elem[(front+1)%MAXSIZE];
	return x;
}

void SeQueue::AddQ(ElemType x)             //进队操作
{
	if ((rear+1)%MAXSIZE==front)
		cout<<"\n Queu is Full!"<<endl;
	else
	{
		rear=(rear+1)%MAXSIZE;
		elem[rear]=x;
	}
}

ElemType SeQueue::DelQ()
{
	if (front==rear)
	{
		cout<<"\n Queue is Empty!"<<endl;            //表明队空,未曾出队
		return -1;
	}
	else{
		front=(front+1)%MAXSIZE;                     //出队操作
		return elem[front];
	}
//SeQueue.cpp
#include "iostream"
#include "SeQueue.h"
using namespace std;

int SeQueue::Empty()                     //判断循环队列是否为空
{
	if (rear==front)
		return 1;
	else  
		return 0;
}

void SeQueue::Display()                  //输出队列
{
	int k;
	if (front==rear)
		cout<<"\n  Queue is Empty!"<<endl;
	else
	{for(k=front;k <= rear;k=(k+1)%MAXSIZE)	cout<<elem[k];
	
	}

}


ElemType SeQueue::GetFront()              //取队列队首元素,不出队
{
	ElemType x;
	if (front==rear){
		cout<<"\n Queu is Empty!"<<endl;
		x=-1;
	}
	else 
		x=elem[(front+1)%MAXSIZE];
	return x;
}

void SeQueue::AddQ(ElemType x)             //进队操作
{
	if ((rear+1)%MAXSIZE==front)
		cout<<"\n Queu is Full!"<<endl;
	else
	{
		rear=(rear+1)%MAXSIZE;
		elem[rear]=x;
	}
}

ElemType SeQueue::DelQ()
{
	if (front==rear)
	{
		cout<<"\n Queue is Empty!"<<endl;            //表明队空,未曾出队
		return -1;
	}
	else{
		front=(front+1)%MAXSIZE;                     //出队操作
		return elem[front];
	}
}

队列的应用-----报数问题

报数问题:设有n个人站成一排,从左到右的编号分别为1~n,从左到右报数”1,2,3,1,2,3“数到”1“和”2“的人出列,数到”3“的人立即站在队伍的最右端。报数过程反复进行,直到n个人都出列为止。

算法思想:先将n个人的编号进队,然后反复执行如下操作:

(1)出队一个元素,输出其编号;

(2)再出队一个元素,输出其编号;

(3)若队列不空,则出队一个元素,然后将该元素再进队。

直到队列为空。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值