小白的数据结构与算法学习笔记(十三)---队列的顺序存储结构及其相关操作

前面介绍的栈是后进先出(LIFO)的一种线性表,今天介绍的队列是先进先出(FIFO)的一种线性表。

栈只允许在栈顶进行插入或删除操作;而队列只允许在队头删除元素(出队列),在队尾插入元素(入队列)。

队列有队头指针指向队头,队尾指针指向队尾。

不管是栈或是队列,都既可以用链表实现,也可以用顺序表实现,但是栈一般采取顺序存储,而队列我们常用链表实现,简称链队列。

为啥队列的顺序存储结构不受青睐呢?下面我们来介绍一下队列的顺序存储结构。

假设现在队列里有n个元素,我们插入只能在队尾,时间复杂度为O(1)。删除只能在队头,如果不移动队头指针,删除操作需要将剩余元素都向前移一个位置,时间复杂度为O(n);如果采取删一个就将头指针往后移一个位置的操作,仿佛解决了这个问题,但是不要忘记我们这是顺序存储结构,空间申请多少就是多少,不能动态增加!这里还要注意一点,此处的尾指针是指向下一个可存放元素的空位置,所以按前面所说,一直删一直删直到尾指针已经指到队列外去了,再想插入元素就会溢出,因为尾指针指的地方已经不属于队列了,然而由于头指针前面还有空位,所以这种现象叫“假溢出”。

怎么解决“假溢出”呢?说白了,就是后面满了的话,就再从头开始呗,也就是要一个头尾相接的循环。

循环队列就好像一个环形存储空间,它依然是队列的顺序存储结构,所以容量固定,并且队头与队尾指针随着元素出入队列发生变化。如何实现循环呢?取模运算。

下面来介绍一下循环队列的相关操作。

1、定义

typedef struct

       ElemType *base;//存放内存分配基地址

       int front;

       int rear;

}

2、初始化

q->base=(ElemType *)malloc(MAXSIZE*sizeof(ElemType));

q->front=q->rear=0;//空队列时头,尾指针指向同一处

3、入队

判断队列是否已满:(q->rear+1)%MAXSIZE==q->front

未满则:q->base[q->rear]=e; q->rear=(q->rear+1)%MAXSIZE;

4、出队

判断队列是否为空:q->front==q->rear;

未空则:*e=q->base[q->front]; q->front=(q->front+1)%MAXSIZE;

                                                                                                                                                     BY   ZJQ

猜你喜欢

转载自blog.csdn.net/qq_41641805/article/details/81534429