数据结构——顺序队列

一、基本概念

只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。进行插入的一端称为队尾(入队列),进行删除操作的一端称为称为队头(出队列),队列具有先进先出(FIFO)的特性。
数据结构——顺序队列_第1张图片
队列的基本操作:

  • 初始化队列
  • 进队列
  • 出队列
  • 判断队列是否为空
  • 判断队列是否已满
    队列可以由数组和链表两种形式实现队列的操作,分别称为顺序队列和链队列
    顺序队列:顺序存储的队列
    链队列:链式存储的队列,长度没有限制

二、顺序队列

我们一直都是用数组来实现顺序存储的,顺序队列也不例外,所以我们需要的是用一个数组int data[MAXSIZE]来存储队列的元素,另外我们还需要两个进行标记下标的数head和tail,来标记队头和队尾。
下面是一个循环队列,基于数组实现的队列的结构:
数据结构——顺序队列_第2张图片
队列通常可以分为两种类型:
①链式队列(由链表实现)。
②静态队列(由数组实现),静态队列通常都必须是循环队列。
由于链式队列跟链表差不多,所以在这里只针对循环队列来说明并实践。
循环队列的两个参数:
①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;
}

你可能感兴趣的:(数据结构)