队列
队列
1.基本概念及描述
队列也是一种特殊的线性表,队列的插入和删除在表的两端进行,插入的那端称为队尾,删除的那端叫做队首,插入和删除操作分别叫做进队和出队。
生活中的排队购票现象就是队列的例子,先到先享受,队列具有“先进先出”(First In First Out)的特点.
2.顺序队列及其实现
C语言中,顺序队列可以使用一维数组来表示。使用两个指针front和rear来标识队首和队尾,front指的是队列最前面,即队首结点在数组元素的下标;rear指的是队尾元素在数组元素下标中的下一个位置,就是即将插入元素的元素在数组中对应的下标。
typedef int datatype;
typedef struct
{
datatype* a;
int capacity;
int front;//指向队首
int rear;//指向队尾元素的下一个数组的下标
}queue;
2.1 基本操作
(1)初始化和销毁
void Init(queue* sq)
{
sq->a = NULL;
sq->capacity = 0;
sq->front = sq->rear = 0;
}
void Destroy(queue* sq)
{
if (sq)
{
free(sq->a);
sq->a = NULL;
sq->capacity = 0;
sq->front = sq->rear = 0;
}
}
(2)获得队首元素的值
datatype Get(queue sq)
{
assert(&sq);
return sq.a[sq.front];
}
(3)插入
void Insert(queue* sq,datatype x)
{
assert(sq);
if (sq->capacity == sq->rear)//扩容
{
int newcapacity = sq->capacity == 0 ? 4 : 2 * sq->capacity;
datatype* tmp = (datatype*)realloc(sq->a, newcapacity * sizeof(datatype*)+1);
if (tmp == NULL)
{
perror("realloc fail");
}
sq->a = tmp;
sq->capacity = newcapacity;
}
sq->a[sq->rear++] = x;
}
(4)删除
void Dele(queue* sq)
{
assert(sq);
sq->front++;
}
3.顺序循环队列及其实现
一个队列经过若干次的插入和删除后,数组的前部可能还有空闲的位置,有空间的浪费。为了有效利用空间,可以将队列想象为一个环状,将数组最前的最后想象为是相邻的,这就是循环队列。
再(b)状态中,如果再插入一个新的结点,数组空间就会被全部占用,此时frontrear,er再状态(c)中,删除一个结点后,也有frontrear,这两种情况条件都相同,如何解决呢?
(1)方法一:
设置一个标志,标识是由于rear增1使得frontrear,还是front增1使得frontrear,前者是队满后者是队空。
(2)方法二:
牺牲一个数组元素的空间,若数组的大小为MAXSIZE,数组最多存MAXSIZE-1个结点。
队满的条件:(rear+1)%MAXSIZE=front;
队空的条件:rear=front;
这里我们实现第一种
3.1 基本操作
(1)插入
void Insert(queue*sq,datatype x)
{
if(sq->rear+1%MAXSIZE==sq->front)
{
printf("队列已满,进行扩容!");
……
}
sq->a[sq->rear]=x;
sq->rear=(sq->rear+1)%MAXSIZE;
}
(2)删除
void Dele(queue*sq)
{
if(sq->front==sq->rear)
{
printf("循环队列是空的,无法操作!!!");
exit(1);
}
sq->front=(sq->front+1)%MAXSIZE;
}