分享一下自己写的数据结构的顺序队列嗯
很多大学刚学数据结构的小伙伴,对于这门课程理解不够深刻,在上机实验中会遇到各种困难,作为过来的小萌新,写下这篇blog希望对需要的朋友有所帮助。咳咳,话不多说,让我们来看看(顺序)队列叭!
什么是队列
详见数据结构课本。通俗的说是一种具有先进先出特性的线性表。
在许多场景下,非常实用。
详细代码如下
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
Status表示一种状态值
typedef int QElemType;//定义队列的结构体
#define QUEUE_INIT_SIZE 3 //定义队列的初始大小
#define QUEUEINCREMENT 1 //定义队列的增量
//以上是数据结构用的前置条件
typedef struct {
QElemType *base;
int front;
int rear;
int MAXQSIZE;
}SqQueue;
//定义队列的结构体此处我写的是顺序队列 链表型的队列代码更简单
//由于我们要做的是循环队列
Status InitQueue(SqQueue &Q)
{
Q.base = (QElemType *)malloc(QUEUE_INIT_SIZE*sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);
Q.front = Q.rear = 0;
Q.MAXQSIZE=QUEUE_INIT_SIZE;
return OK;
}
//判断队列是否为空 若空返回TRUE 不空则返回FALSE;
Status QueueEmpty(SqQueue Q)
{
if(Q.front==Q.rear)
return TRUE;
else return FALSE;
}
//输出函数
void putoutQueue(SqQueue Q)
{
if(!QueueEmpty(Q))
{
printf("当前队列的元素有:");
int i = Q.front;
while (i != Q.rear)
{
printf("%3d",Q.base[i]);
i=(i+1)%Q.MAXQSIZE;
}
printf("\n");
}
else printf("当前队列为空\n");
}
//求队列长度
int QueueLength(SqQueue Q)
{
return (Q.rear - Q.front + Q.MAXQSIZE)%Q.MAXQSIZE;
}
// 循环队列,的插入元素问题 等会解释
Status EnQueue(SqQueue &Q,QElemType e)
{
int i,j,k;
if((Q.rear+1)%Q.MAXQSIZE == Q.front) //队列满 追加空间
{
Q.base = (QElemType *)realloc(Q.base,(Q.MAXQSIZE + QUEUEINCREMENT)* sizeof(QElemType));
if(!Q.base)
exit(OVERFLOW); //分配内存失败
if(Q.rear<Q.front) //若rear<front 将front之后元素移动到新增空间
{ //
for(i=Q.MAXQSIZE-1,j=Q.MAXQSIZE+QUEUEINCREMENT-1;i>=Q.front;i--,j--)
Q.base[j]=Q.base[i];
k=Q.MAXQSIZE-Q.front;
Q.MAXQSIZE+=QUEUEINCREMENT;
Q.front=Q.MAXQSIZE-k;
}
else
Q.MAXQSIZE+=QUEUEINCREMENT;
}
Q.base[Q.rear]=e;
Q.rear = (Q.rear+1)%Q.MAXQSIZE;
return OK;
}
Status DeQueue(SqQueue &Q,QElemType &e)
{
if(Q.front==Q.rear)
return ERROR;
e=Q.base[Q.front];
Q.front = (Q.front+1)%Q.MAXQSIZE;
return OK;
}
Status GetHead(SqQueue &Q,QElemType &e)
{
if(Q.front==Q.rear)
return ERROR;
e=Q.base[Q.front];
return OK;
}
void ClearQueue(SqQueue &Q)
{
QElemType e;
while(!QueueEmpty(Q))
DeQueue(Q,e);
printf("清空完成\n");
}
void assign(SqQueue &Q)
{
int m,i;
QElemType e;
printf("输入队列中元素个数: ");
scanf("%d",&m);
for(i=0;i<m;i++)
{
printf("请输入元素: ");
scanf("%d",&e);
EnQueue(Q,e);
}
}
void feibo(SqQueue &Q,int k)
{
InitQueue(Q);
for(int i=0;i<k;i++)
{
if(i<2) //出口
{
Q.base[Q.rear] = 1;
Q.rear = (Q.rear+1)%Q.MAXQSIZE;
}
else
{
if((Q.rear+1)%Q.MAXQSIZE == Q.front) //队列满 追加空间
{
Q.base = (QElemType *)realloc(Q.base,(Q.MAXQSIZE + QUEUEINCREMENT)* sizeof(QElemType));
if(!Q.base)
exit(OVERFLOW); //分配内存失败
//
int a,b;
if(Q.rear<Q.front) //若rear<front 将front之后元素移动到新增空间
{ //
for(a=Q.MAXQSIZE-1,b=Q.MAXQSIZE+QUEUEINCREMENT-1;a>=Q.front;a--,b--)
Q.base[b]=Q.base[a];
int m=Q.MAXQSIZE-Q.front;
Q.MAXQSIZE+=QUEUEINCREMENT;
Q.front=Q.MAXQSIZE-m;
}
else
Q.MAXQSIZE+=QUEUEINCREMENT;
}
Q.base[Q.rear] = Q.base[(Q.rear-1)%Q.MAXQSIZE]+Q.base[(Q.rear-2)%Q.MAXQSIZE];
Q.rear = (Q.rear+1)%Q.MAXQSIZE;
}
}
putoutQueue(Q);
printf("执行完毕\n");
ClearQueue(Q);
}
Status menu()
{
int code;
printf("\n\t菜单\n");
printf("1)--初始化队列\t2)--给队列赋值\n");
printf("3)--入队\t4)--出队 \n");
printf("5)--清空队列 \t6)--队列长度 \n");
printf("7)--对头元素 \t8)--打印队列 \n");
printf("9)--斐波那契 \t10)--退出 \n");
printf("----------------------------------------\n");
printf("你的选择:(1 ~ 10) ");
fflush(stdin);
scanf("%d",&code);
return code;
}
void main()
{
int code;
int k,length;
QElemType e;
SqQueue Q;
Q.base = NULL;
do
{
code=menu();
switch(code)
{
case 1: if(InitQueue(Q))
printf("初始化成功\n");
break;
case 2:if(Q.base)
assign(Q);
else printf("请初始化队列\n");
break;
case 3: if(Q.base)
{
printf("请输入入队元素值: ");
scanf("%d",&e);
if(EnQueue(Q,e))
printf("%d入队成功\n",e);
else printf("入队失败\n");
}
else printf("请初始化队列\n");
break;
case 4: if(Q.base)
{
if(DeQueue(Q,e))
printf("出队成功!出队元素是%d\n",e);
else printf("出队失败\n");
}
else printf("请初始化队列\n");
break;
case 5: ClearQueue(Q);
break;
case 6: if(Q.base)
{
length = QueueLength(Q);
printf("当前队列长度为:%d",length);
}
else printf("请初始化队列\n");
break;
case 7: if(Q.base)
{
if(GetHead(Q,e))
printf("读取成功队头元素是%d\n",e);
else printf("读取失败\n");
}
else printf("请初始化队列\n");
break;
case 8: if(Q.base)
putoutQueue(Q);
else printf("请初始化队列\n");
break;
case 9: printf("Thanks for using!\n");
exit(0);
}
}while(code>=0 && code<10);
printf("Thanks for using!\n");
}
我觉得吧已经鸽了很久的介绍。太不走心了。
简单解释下循环队列追加空间什么的问题。
经过和小伙伴们的讨论分析,对于满队列追加空间的重新定位有两种解决办法(一种是固定队首,一种是固定队尾),怎么理解具体看下图吧。画的不好见谅。
主要是为了解决有其他元素入出队列的队首队尾重定位问题
把一个定长的顺序列拉成一个圈,可以清晰的认知。队首队尾虽然在变,但在顺序列中是有固定的标号的。主要是计算新增空间后各个元素的位置应该怎么移动,队首队尾如何变化。