队的定义
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列的抽象数据类型
数据部分:
线性表的数据元素同类型,相邻元素具有前驱和后驱关系
操作部分:
1 建立空队列
2 释放队列的存储空间
3 从队尾插入新的元素
4 从队头删除元素
队列的顺序存储结构
循环队列
循环队列其实就是队列的顺序存储结构,即元素在存储空间上是连续的。
定义front指针指向队头,rear指针指向队尾元素的的后一个空闲元素位置。
判断队列是否为空:
rear == front
判断队列是否队满:
为了区别于队空的判断条件,规定队满时,rear后面保留一个空闲元素。由于是循环队列,rear可能会大于front, 也有可能小于front,假设队列长度为SIZE。、
1 当front > rear时,若rear + 1 = front,即(rear + 1)% SIZE = front。
2 当rear > front时,唯一队满的情况就是front指向第一个,rear 指向倒数第二个。rear + 1 = SIZE,此时front 也指向下标为0的结点,故依然满足(rear + 1)% SIZE = front。
计算队列长度:
当front > rear时,队列长度分为两段,一段是SIZE - front,另一段是rear - 0,然后相加:rear - front + SIZE。
当rear > front时,队列长度就为rear - front。
为了统一公式:rear - front是二者共同点,(rear - front + SIZE)%SIZE
循环队列抽象数据类型实现
定义数据类型:
结构体需要数据域,需要记录队头的下标的front变量和记录队尾下标的rear变量。
代码如下:
#include <stdio.h>
#define SIZE 20
typedef int QElemType;
typedef struct
{
QElemType data[SIZE];
int front;
int rear;
}
队列的初始化:
队列的初始化就是给队头front和队尾rear都赋0.
代码如下:
Status Init_Queue(Queue *init_queue)
{
init_queue->front = 0;
init_queue->rear = 0;
return OK;
}
求队列长度:
就是利用公式(rear - front + SIZE)%SIZE
代码如下:
int obtain_longth(Queue *queue)
{
return (queue->rear - queue->front + SIZE) % SIZE;
}
入队操作:
1 判断队满:(rear + 1)% SIZE = front
2 赋值给数据域
3 队尾后移一位(rear + 1)% SIZE
代码如下:
Status IN_Queue(Queue *in_queue, QElemType new_data)
{
if((in_queue->rear +1 )%SIZE == in_queue->front)
return ERROR;
in_queue->data[in_queue->rear] = new_data;
in_queue->rear = (in_queue->rear +1 )%SIZE;
return ERROR;
}
出队操作:
1 判断队列是否为空:rear=front
2 把front的值赋给删除元素指针
3 front向后移动一位(front + 1)%SIZE
代码如下:
Status OUT_Queue(Queue *out_queue, QElemType *delete_data)
{
if(out_queue->rear == out_queue->front)
return ERROR;
*delete_data = out_queue->data[out_queue->front];
out_queue->front = (out_queue->front +1 )%SIZE;
return ERROR;
}
队列的链式存储结构及实现
定义数据类型:
1 定义链表结点
2 定义存储队头、队尾指针的结构体,通过它,来操作队链表。
typedef struct Qnode
{
QElemType data;
struct Qnode *next;
}Qnode,*QUEUPTR;
typedef struct
{
QUEUPTR front,rear;
}linkqueue;
入队操作:
1 rear->next = newnode。rear = newnode。rear->next = NULL。
Status IN_Link_Queue(linkqueue *PTR,QElemType new_data)
{
QUEUPTR new_node;
new_node = (QUEUPTR)malloc(sizeof(Qnode));
if(!new_node)
return ERROR;
PTR->rear->next = new_node;
PTR->rear = new_node;
new_node ->data = new_data;
new_node ->next = NULL;
return OK;
}
出队操作:
1 判断链表是否为空,rear= front
2 delete_node = front,delete_node->data给删除数据指针,delete_node->next 赋值给front->next。
3 如果被删除的结点是队尾,则将尾指针指向头结点。
4 free(delete_node )
代码如下:
Status OUT_Link_Queue(linkqueue *PTR,QElemType *delete_data)
{
QUEUPTR delete_node;
if(PTR->front == PTR->rear)
return ERROR;
delete_node = PTR->front->next;
*delete_data = delete_node->data;
PTR->front->next = delete_node ->next;
if(PTR->rear == delete_node)
PTR->rear = PTR->front;
free(delete_node);
return OK;
}