引入:
队列和栈一样都属于特殊的线性表
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
操作:队尾进行插入操作,队头进行删除操作。
先入先出 的线性表
队列我们现实生活中经常会遇到:
比如电脑有时会进入假死状态,不动了,然后一段时间后突然把你刚做的操作全部按顺序执行一遍,这个就是多个程序需要通过一个通道输出,而按先后次序排队等待造成的。
还有银行的排队取号系统,电脑键盘的输入等都是队列的案例。
所以队列很重要,需要着重学习。
一.队列的顺序存储:
假如我们在窗口买票,一个人买完了出去了,后面的所有人都要跟着往前移动一个。
买票还行,但是在数组中这种效率是比较差的,为了解决这个问题,加个指针就行了,
到谁了就指向谁,没有必要非要向前移动。
同时为了避免只有一个元素时,队头和队尾重合使处理变的麻烦,所以引入两个指针,front指向队头元素,rear指针指向队尾元素。
typedef int datatype ; /*定义队列中数据元素的数据类型*/
#define MAXSIZE 64 /*定义队列的容量*/
typedef struct
{ datatype data[MAXSIZE] ; /*用数组作为队列的储存空间*/
int front,rear ; /*指示队头位置和队尾位置的指针*/
} sequeue,*seq_pqueue;
入队:(表尾插入)
但是还有一个问题,由于不需要必须从0位置出队列,头指针在不断向后走,此时
队列长度就只有5,头指针在2的位置,对列中此时有三个元素,此时再入队,尾指针就移动到数组外面了,但是队列前面还空闲着呢。
让我想起了北京的公交,每次都是前门被挤爆,后门位置还空着呢,车上明明有空间,车下的人就是上不来。(假溢出)
为了解决这种尴尬事情,就出现了循环队列。后面满了,就从头开始,让首尾相接。
什么时候说明队列满了?
front=rear说明队列满,但是front=rear也说明队列为空。
如何进行区分??
(rear+1)% queuesize == front,用这种方法来判断队列满。(浪费一个空间)
1.循环队列的初始化
void init_seqqueue(seq_pqueue *Q)//Q为指针的指针
{
*Q=(seq_pqueue)malloc(sizeof(seq_queue));
if((*Q)==NULL)
{
perror("malloc");
exit(-1);
}
(*Q)->front=(*Q)->rear=MAXsize -1;
return;
}
2.入队:(队尾插入)
bool in_seqqueue(datatype data,seq_pqueue q)
{
if(is_full_seqqueue(q)){
return false;
}
q->rear=(q->rear+1)%MAXSIZE;
q->data[q->rear]=data;
return true;
}
3.出队:(表头删除)
bool out_seqqueue(seq_pqueue q,datatype *D)
{
if(is_empty_seqqueue(q)){
return false;
}
q->front=(q->front+1)%MAXSIZE;
*D=q->data[q->front];
return true;
}
二.队列的链式存储:
只能尾进头出的单链表,和单链表操作没有什么区别。
只是多了头指针和尾指针。
1.
typedef struct linkqueuenode{
datatype data;
struct linkqueuenode *next;
}linkqueue_node,*linkqueue_pnode;
typedef struct linkqueue{
linkqueue_pnode front,rear;
}link_queue,*link_pqueue;
表尾插入,表头删除。
2.插入操作(表尾插入)
bool in_linkqueue(datatype data,link_pqueue q)
{
linkqueue_pnode new;
new=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
if(new==NULL)
{
return false;
}
new->data=data;
new->next=q->rear->next;
q->rear->next=new;
q->rear=q->rear->next;
return true;
}
3.出队列:删除操作(表头删除)
头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外值剩下一个元素时,则需将rear指向头结点。
bool out_linkqueue(link_pqueue q,datatype *D)
{
linkqueue_pnode t;
if(q->rear == q->front){
return false;
}
t=q->front;
q->front =q->front->next;
*D=q->front->data;
free(t);
return true;
}