队列的创建和基本使用

队:在队尾插入,队头删除(头删尾插)

常见的一些应用有:脱机打印输出、多用户系统、网文电文传输

根据存储方式的不同可以分为:顺序队和链队

一、顺序栈:

结构体的定义:

typedef struct {
	QElemType* base; //动态分配存储空间
	int front;//头指针
	int rear;//尾指针,指向下一个元素
}SqQueue;
代码中的QElemType为自行定义的数据类型,可根据需要自行定义:例如要整形则:
typedef  int  QElemType;   这样即将QElemType定义为int型。

 

注意:在进行插入和删除元素的过程中可以会出现假溢出的情况

假溢出:即rear指针已经指向最大的存储范围了,可是front指针却并没有直指向0,且队中

任然有空间可以存储元素

解决方案:使用循环队列

即:将队的存储空间看成一个循环的表,使分配给队的m个存储单元可以循环使用,当rear指针指向最大范围时,若队中的开始端还有空的空间则会返回到开头,即又可以从头开始使用空间,front指针同样如此。

实现方法则采用:模运算

队列的初始化:


Status Init(SqQueue& Q) {
	Q.base = new QElemType[100]; //为队尾指针分配存储空间
	if (!Q.base) false;
	Q.front = Q.rear = 0;  //队空
	return true;
}

 代码中的Status 和上述的QElemType一样为自己根据需要求定义的数据类型

求队列的长度:


int Length(SqQueue Q) {
	return (Q.rear - Q.base + 100) % 100;
}
//利用求模运算求出队的真实长度

入队:


Status En(SqQueue& Q, QElemType e) {
	if ((Q.rear + 1) % 100 == Q.front) //判断是否为队满
		return false;
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % 100; //利用求模运算确定rear的移动位置
	reutrn true;
 }

出队:


Status Chudui(SqQueue& Q QElemType& e) {
	if (Q.front == Q.rear)
		return false;
	e = Q.base[Q.front]; 
	Q.front = (Q.front + 1) % 100; //利用求模运算确定front的移动位置
	return true;
}

 

 取队头元素:


SElemType Get(SqQueue Q) {
	if (Q.front != Q.rear)
		return Q.base[Q.front];
}

补充说明:因为上述代码中队采用的是循环队列,所以其队空时和队满时的条件相同

解决该问题的方案有:1、另外设一个标志以区别队空和队满

                                    2、另外设一个变量,记录存储元素个数

                                    3、少用一个元素空间(大多采用该方法)

少用一个元素空间:队空时:front=rear;

                                队满时:(rear+1)%最大存储范围=front;

 

链队:若用户无法估计所用队列的长度,则宜采用链队

链队的结构体类型定义:


typedef struct Qnode {
	QElemType data;
	stuct Qnode* next;
}QNode,*QuenePtr;

typedef struct {
	QuenePtr front;
	QuenePtr rear;
}LinkQueue;

代码中的QElemType为自行定义的数据类型,可根据需要自行定义

该代码中定义了两个结构体:主要原因是,在使用链队中指针front和rear都同时需要两个变量的数据类型所以,第一个结构体变量是为第二结构体所需的数据类型所定义的

 链队列初始化:


Status Init(LinkQueue& Q) {
	Q.front = Q.rear = (QuenePtr)malloc(sizeof(QNode));
	Q.front->next=NULL:
	return true;
}

代码中的Status为自行定义的数据类型,可根据需要自行定义

 

链队列的销毁:


Status Destroy(LinkQueue& Q) {
	while (Q.front) {
		LinkQueue p;  //创建一个新的结点p
		p = Q.front->next;  //使p指向Q的front所指向的结点的后继
		free(Q.front);
		Q.front = p;  //将front的后一个结点重新传给front
		return true;
	}
}  //循环往复直到front为空

将元素e入队:


Status IN(LinkQueue& Q, QElemType, e) {
	p = (QuenePtr)malloc(sizeof(QNode)); //为p分配存储空间
	if (!p)  return false;
	p->data = e;  //将e赋值给p的数据域
	p->next = NULL; //使p的后继指针指向空
	Q.rear->next = p; //让原来的最后一个结点的后继指针指向p结点
	Q.rear = p; //使尾指针rear指向p
}

出队:


Status Out(LinkQueue& Q, QElemType& e) {
	if (Q.front == Q.rear) //判断队是否为空
		return false;
	p = Q.front->next; //使p结点指向头结点
	e = p->data;    //将头结点的数据域的值赋值给e
	Q.front->next = p->next; //使头结点的后继指向p的后继结点(即front原先所指的后继结点的后继)
	if (Q.rear == p)      //判断删除的是否为使尾结点
		Q.rear = Q.front;
	delete p;
	return true;
}

求队头元素


QElemType Out(LinkQueue& Q, QElemType& e) {
	if (Q.front == Q.rear)
		return 0;
	e = Q.front->next->data;//将头结点所指的后继结点的数据域赋值给e
     return e;
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值