从“追求尽量不出错”,到正视“出错是|

如此而已~~~

园龄:3年3个月粉丝:0关注:12

C语言数据结构队列

C语言数据结构队列

队列也有顺序储存与链式储存(此处我以顺序为例)

队列:类似于排队,一般是队尾入队,队头出队。

队列的一般形式

一种是:利用数组分配一段连续的内存空间。

另一种是:动态分配一个连续的内存空间。

首先定义一个队列的结构体类型:

typedef struct SqQueue//定义一个顺序队列的结构体类型 
{
int *base;//用于记录存储空间的基地址
int front;//“头指针”
int rear;//"尾指针"
}SqQueue;

初始化:

void InitQueue(SqQueue *Q)
{
Q->base=(int *)malloc(sizeof(int)*MAX);//由结构体指针接受并返回这段连续的内存空间的基地址
if(Q->base==NULL)
{
printf("分配空间失败!\n");
exit(1);
}
Q->front=Q->rear=0;//初始化时将“头指针”和“尾指针”都指向这段连续空间的首地址
return;
}

对于此类队列:

    1. 队列需要一个头指针与一个尾指针
    2. 头指针:front

      尾指针:rear
    1. 初始化队列
    2. 分配一段连续的内存空间


      将front=rear=0

    1. 入队与出队
    2. 入队:rear++,front不动


    出队:front++,rear不动

但是:

这样就会出现”假溢出“的情况(即队尾指针移动到底但是队头出队又留下了新的空间)

所以这里我们引入一个新的概念“循环队列”

即再队尾指针指向连续空间末尾时,下一次会重新回到这个连续空间的首地址。 这样便有效的避免了假溢出的现象 而新的问题又出现了

  1. 使用了这一个循环队列如何描述队尾与队头指针的移动?
  2. 如何解决Q.rear==Q.front在循环队列中的二义性?
  3. 如何求取循环队列的长度问题?

以下个人见解:

这里引入:
    1. 模运算即以Q.rear=(Q.rear+1)%Max与Q.front=(Q.front+1)%Max来描述指针的移动。
    2. 如其值等于Max-1时+1%Max将会重回0号位置,而在此之前均表示向后移动一位(Max表示队列最大长度)

    3. 重新设置队满条件即(Q.rear+1)%Max==Q.front时表示队满此时其实队列仍有一个空位置。
    4. 但是为了保证Q.rear==Q.front是表示队空的情况,即是由出队Q.front=(Q.front+1)%Max追上Q.rear时的情况。

    5. 求队的长度
    6. 再循环队列中会出现两种情况: a.此类情况是当队尾指针与队头指针都没有进入相对于对方的下一次循环中即


      Q.rear-Q.front的值为正的情况下此时队长就是两者的差值

      b.而另一类情况则是在Q.rear进入下一次循环时Q.front还未进入下一次循环即

      Q.rear-Q.front的值为负的情况下此时队长是(Q.rear-Q.front+Max)

      此处个人理解解释:此时队长应为(Q.front-Q.rear)相对于Max的"补集"的长度!!!!!!

      而为了统一a类与b类的形式此处使用"(Q.rear-Q.front+Max)%Max"

      这样既不会对a产生影响,且直接在()内部直接完成了对b类补集的计算。

参考代码:

#include <stdio.h>
#include <stdlib.h>
//构造队列数据类型
#define MAX 6
typedef struct SqQueue
{
int *base;//用于记录存储空间的基地址
int front;
int rear;
}SqQueue;

//初始化队列
void InitQueue(SqQueue *Q)
{
Q->base=(int *)malloc(sizeof(int)*MAX);
if(Q->base==NULL)
{
printf("分配空间失败!\n");
exit(1);
}
Q->front=Q->rear=0;
return;
}

//求循环队列长度
int QueueLength(SqQueue *Q)
{
return (Q->rear-Q->front+MAX)%MAX;
}

//入队函数
void EnQueue(SqQueue *Q,int e)
{
if((Q->rear+1)%MAX==Q->front)//尾指针在循环意义上加1后等于头指针表明队满
{
printf("队列已满,无法入队!\n");
return;
}
Q->base[Q->rear]=e;//新元素插入队尾
Q->rear=(Q->rear+1)%MAX;//队尾指针加1
return;
}

//出队函数
int DeQueue(SqQueue *Q)
{
if(Q->front==Q->rear)
{
return 0;
}
int e;
e=Q->base[Q->front];//保存队头元素
Q->front=(Q->front+1)%MAX;//队头指针加1
return e;
}

//取循环队列对头元素
int GetHead(SqQueue *Q)
{
if(Q->front!=Q->rear)//队列非空
{
return Q->base[Q->front];
}
else
{
printf("队列已空,无法出队!\n");
return 0;
}
}
int main()
{
SqQueue Q;
int num,e;
InitQueue(&Q);
printf("输入你需要的指令:\n");
printf("----结束(0)----\n");
printf("----入队(1)----\n");
printf("----出队(2)----\n");
scanf("%d",&num);//先输入一个指令
while(num>0)
{
switch(num)
{
case 1:
   printf("队列入队:\n");
scanf("%d",&e);
EnQueue(&Q,e);
   break;
case 2:
   e=DeQueue(&Q);
   if(e==0)
{
 printf("队列已空,无法出队!\n");
 break;
  }
   printf("出队元素为:\n");
   printf("%d\n",e);
   break;
default :
printf("你输入的指令有误!\n");
}
printf("你的下一步指令是:\n");
scanf("%d",&num);//接着继续输入一个指令
}
return 0;
}
 

本文作者:如此而已~~~

本文链接:https://www.cnblogs.com/fragmentary/p/16160900.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   如此而已~~~  阅读(177)  评论(0编辑  收藏  举报
//雪花飘落效果
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起