一、基本概念
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。进行插入的一端称为队尾(入队列),进行删除操作的一端称为称为队头(出队列),队列具有先进先出(FIFO)的特性。
队列的基本操作:
- 初始化队列
- 进队列
- 出队列
- 判断队列是否为空
- 判断队列是否已满
队列可以由数组和链表两种形式实现队列的操作,分别称为顺序队列和链队列
顺序队列:顺序存储的队列
链队列:链式存储的队列,长度没有限制
二、顺序队列
我们一直都是用数组来实现顺序存储的,顺序队列也不例外,所以我们需要的是用一个数组int data[MAXSIZE]来存储队列的元素,另外我们还需要两个进行标记下标的数head和tail,来标记队头和队尾。
下面是一个循环队列,基于数组实现的队列的结构:
队列通常可以分为两种类型:
①链式队列(由链表实现)。
②静态队列(由数组实现),静态队列通常都必须是循环队列。
由于链式队列跟链表差不多,所以在这里只针对循环队列来说明并实践。
循环队列的两个参数:
①head,head指向队列的第一个元素。
②tail,tail指向队列的最后一个有效元素的下一元素。
队列的两个基本操作:出队和入队。
三、实现
1、顺序队列的初始化和打印
void SeqQInit(SeqQ* sq){
if (sq == NULL){
return;
}
sq->size = 0;
sq->head = 0;
sq->tail = 0;
}
void SeqQPrint(SeqQ* sq, const char* msg){
printf("[%s]\n", msg);
if (sq == NULL){
return;
}
int i = sq->head;
for (; i<sq->tail; i++){
printf("[%c|%p]", sq->data[i]);
}
printf("\n");
}
2、销毁和进行扩容
void SeqQDestroy(SeqQ* sq){
if (sq == NULL){
return;
}
sq->size = 0;
sq->head = 0;
sq->tail = 0;
}
void SeqQResize(SeqQ* sq){
if (sq == NULL){
return;
}
if (sq->size <= MAXSIZE){
return;
}
int size = MAXSIZE * 2 + 1;
SeqQType* new = (SeqQType*)malloc(sizeof(SeqQType));
int i = 0;
for (; i<sq->size; i++){
new[i] = sq->data[i];
}
free(sq->data);
}
3、入队列
void SeqQPush(SeqQ* sq, SeqQType value){
if (sq == NULL){
return;
}
if (sq->size>=MAXSIZE){
SeqQResize(sq);
return;
}
sq->data[sq->tail++] = value;
if (sq->tail == MAXSIZE){
sq->tail = 0;
}
++sq->size;
}
4、出队列
我们在进行顺序队列的时候,当我们想要进行出队列操作的时候,我们主要实现的过程就是让我们的head-1,让tail进行加1操作,这样就能实现将我们不要的元素进行出队列。
void SeqQPop(SeqQ* sq){
if (sq == NULL){
return;
}
if (sq->size == 0){
return;
}
++sq->head;
if (sq->head >= MAXSIZE){
sq->head = 0;
}
--sq->size;
}
5、取队首元素
取队首元素的时候我们直接就考虑取head指向的元素,这就是队首元素。队列遵循的原则是先进先出,所以我们直接取head下标指向的元素就是我们最后想要的元素。
int SeqQFront(SeqQ* sq, SeqQType* value){
if (sq == NULL || value==NULL){
return -1;
}
if (sq->size == 0){
return -1;
}
*value = sq->data[(sq->head)];//注意在这里考虑优先级的问题
return *value;
}
相关的测试函数
#defineTEST_HEADE printf("\n===========%s==============\n",__FUNCTION__);
void test1(){
SeqQ sq;
SeqQInit(&sq);
SeqQPush(&sq, 'a');
SeqQPush(&sq, 'b');
SeqQPush(&sq, 'c');
SeqQPush(&sq, 'd');
SeqQPrint(&sq, "入队列四个元素");
}
void test2(){
SeqQ sq;
SeqQInit(&sq);
SeqQPush(&sq, 'a');
SeqQPush(&sq, 'b');
SeqQPush(&sq, 'c');
SeqQPush(&sq, 'd');
SeqQPrint(&sq, "入队列四个元素");
SeqQPop(&sq);
SeqQPrint(&sq, "出队列一个元素");
SeqQPop(&sq);
SeqQPrint(&sq, "出队列两个元素");
SeqQPop(&sq);
SeqQPrint(&sq, "出队列三个元素");
SeqQPop(&sq);
SeqQPrint(&sq, "出队列四个元素");
}
void test3(){
SeqQ sq;
SeqQInit(&sq);
SeqQPush(&sq, 'g');
SeqQPush(&sq, 'b');
SeqQPush(&sq, 'c');
SeqQPush(&sq, 'd');
SeqQPrint(&sq, "入队列四个元素");
SeqQType value;
int i = SeqQFront(&sq, &value);
printf("%c\n", i);
}
int main(){
test1();
test2();
test3();
getchar();
return;
}