1.基本定义
一个队列应该保存:数据,最大可存储空间maxsize,头指针front,尾指针rear
2.队列特征
只允许一端插入,另一端删除。
特征:先进先出 (first in frist out)FIFO
后进后出(last in last out)LILO
特殊在操作:操作受限制
3.顺序存储结构
3.1顺序存储遇到的问题
基于顺序存储的队列
特点是简单方便,容易遇到的问题是假溢出:明明前面还有空间,但是队列却不能再入队了。
因此提出了环形队列这一思想。
3.2环形队列
把连续的空间看作一个环,让连续空间最后的地址和前面的地址连接起来,这样就可以充分利用空间了!
怎么做?模运算!
3.3环形队列如何初始化
#include <stdio.h>
#include <stdlib.h>
//主要讲环型队列
#define maxsize 20
struct node
{
int *data;
int front,rear;
int maxsize;
};
typedef struct node * queue;
queue createQueue(int maxsize)
{
queue q=(queue)malloc(sizeof(struct node));
q->data=(int*)malloc(sizeof(int)*maxsize);
q->front=0;
q->rear=0;
return q;
}
可以看出,队列空的时候front==rear==0
入队的时候就让rear++,那么rear=1
也就是说,front指向的是一个空地址,front下一个才真正是我们存储元素的队列!rear指向的是队列中实际的最后一个元素的位置!
3.4判断队列是否为空&是否满
int isEmpty(queue q)
{
return a->front==q->rear;
}
int isFull(queue q)
{
return q->front==(q->rear+1)%(q->maxsize);
//判断队列满的条件是rear+1==front,
//但是为什么要%maxsize呢,想想这样的情况:front指向0(始终没有出队),rear指向存储空间的末尾,这也叫队列满了,这时rear+1正好等于maxsize,那么%maxsize==front==0
//这就对味了
//这不正是所谓的环形队列的思想吗
}
3.5入队&出队
//入队
int push(queue q,char x)
{
if(isFull(q)){
print("队列满");
return 0;
}
else{
q->rear=(a->rear+1)%q->maxsize;
//rear指针先挪到下一个元素应该在的位置
q->data[q->rear]=x;//元素入队!
return 1;//成功入队返回1
}
}
//出队
int pop(queue q)
{
if(isEmpty(q)){
printf("队列空");
return 0;
}
else{
q->front=(q->front+1)%q->maxsize;
//front指针先挪到该删除元素所在的位置
return q->data[q->front]; 返回这个元素
}
}
4.基于链式存储方案
4.1定义以及初始化
我们需要两个结构体:
1)node就是实在的节点,存储数据为data和指向下一个节点的指针next
2)qnode才是我们之后要去操作的东西,也就是队列queue,注意下面的typedef,包含的数据为front,rear,分别指向队列这个串的头节点和尾节点,还有一个就是队列大小queuesize
我们初始化就是初始化一个queue,因为还没有数据,所以front和rear都指向NULL,然后返回q
注意:我们的链表不带头结点!所以对于链表为空或只有有一个元素时需要特殊处理
#include<stdio.h>
#include<stdlib.h>
struct node
{
char data;
struct node * next;
};
typedef struct node* position;
struct qnode
{
position front,rear;
int queuesize;
};
typedef struct qnode* queue;
queue createQueue()
{
queue q;
q=(queue)malloc(sizeof(struct qnode));
q->front=NULL;
q->rear=NULL;
return q;
}
4.2判断为空
//判断队列是否为空
int isEmpty(queue q)
{
return (q->front==NULL)
}
4.3求队列长度
//求队列长度
int queueSize(queue q)
{
int i=0;
position p=q->front;
while(p!=NULL){
i++;
p=p->next;
}
return i;
}
4.4入队
- 申请一个新节点frontcell
- q为空时特殊处理,首尾指针都指向frontcell。
- 否则将frontcell加入到队列最后,也就是链表最后
- 然后再把rear指向front
int addq(queue q,char x)
{
position frontcell;
//申请空间
frontcell=(position)malloc(sizeof(struct node));
if(!frontcell){
printf("申请空间失败");
return 0;
}
else{
frontcell->data=x;
frontcell->next=null;
if(isEmpty(q)){
q->front=frontcell;//只有一个元素
q->rear=frontcell;
}
else{
q->rear->next=frontcell;//加入到最后,也就是链表的最后
q->rear=frontcell;
return 1;
}
}
4.5出队
- 队列空时特殊处理
- frontcell指向队首元素
- 队列只有一个元素特殊处理
- 否则就把front指针向后移动一个,然后free(frontcell)
//出队
char deleteq(queue q)
{
position frontcell;
char frontdata;
if(isEmpty()){
printf("队列空");
return 0;
}
else{
frontcell=q->front;
if(q->front==q->rear)
q->front=q->rear=NULL;
else
q->front=q->front->next;
frontdata=frontcell->data;
free(frontcell);//删除节点释放空间
return frontdata;
}
}