循环队列的介绍

队列

队列就是一个能够实现“先进先出”的存储结构。队列分为链式队列和静态队列;静态队列一般用数组来实现,但此时的队列必须是循环队列,否则会造成巨大的内存浪费;链式队列是用链表来实现队列

循环队列

牺牲一个元素空间的前提

需要两个指针 :tail (队尾指针)head(队头指针)

  1. 队列初始化时,两个值都为0

  2. 当队列不为空时,head指向队列第一个元素,tail指向队列最后一个元素的下一个位置,也就下一个元素入队时要放在rear的位置上,而tail“顺延”

  3. 当tail == head 时, 队列可以为满的,也可以为空的。

    满:(tail +1) %MAXSIZE == head

    空: head==rear

队列的长度:

当tial大于head时: len = tail-head

tail小于head时 : len= tail - head+MAXSIZE

合并起来就是: (tail-head+MAXSIZE )%MAXSIZE

取余的理解

理解:
当tail追上head时,队满。 当head追上tail时, 队空。

如果想让一个数约束在 0~n的范围内, 需要将x%n

或者这样理解: 循环队列要解决的问题就是要防止指针越界,所以当tail在数组的 边界值,+1就会越界时,就需要用一个神奇的操作 : mod 。

队列的操作

获取: 对头元素:buff[front]

获取: 队尾元素: buff[tail-1 ]


#include  
#include  
#include 


struct Queue
{
	int tail ;          //队尾指针
	int head  ;         //队头指针
	char* base;         //数据数组
	int maxsize;         
};
typedef struct Queue queue;

 queue *  initQueue(queue* queue ,int maxsize )
 {
	 if (queue == NULL)
	 {
		 queue = (struct Queue*)malloc(sizeof(struct Queue));
	 }
	 queue->base = (char*) malloc( sizeof(char) * maxsize );
	 if (queue->base  == NULL)
	 {
		 exit(0); 
	 }
	 queue->head = queue->tail = 0;
	 queue->maxsize =maxsize ; 
	 return queue; 
 }


 bool   isFull(queue* queue)
 {
	 if (queue == NULL) return false ;
	 return ( (queue->tail + 1) % queue->maxsize  == queue->head); 
 }
 void add(queue* queue, char data)
 {
	// 判断是否队满
	 if (isFull(queue))
	 {
		 printf("队列已满!, 元素 %c 无法入队 \n" ,data )  ;
			 return ; 
	 }
	 queue->base[queue->tail] = data;
	 queue->tail = (queue->tail + 1) % queue->maxsize;  //注意这里tail的变化。 
	
 }
 int count(queue* queue)
 {
	 if (queue == NULL) return 0;
	 return (queue->tail - queue->head+queue->maxsize ) % queue->maxsize;  
 }
 bool isEmpty(queue* queue)
 {
	 if (queue == NULL) return false;
	 return (queue->head == queue->tail); 
 }
 char  Dequeue(queue* queue)
 {
	 if (isEmpty(queue))
	 {
		 printf("队列已空!\n"); return NULL ; 
	 }
	 char ch = queue->base[queue->head];  
	 queue->head = (queue->head + 1) % queue->maxsize;
	 return ch;
 }
 void queueTravel(queue* queue)
 {
	 int head = queue->head, tail = queue->tail;
	 while (head != tail)
	 {
		 printf("%2c",queue->base[head]);
		 head = ( head + 1) % queue->maxsize;
	 }
 }
 int main()
 {
	 queue *Q =NULL ;
	 char arr[14] = { 'a','b','c','d','e','f','g','h','a','d','s' ,'e','s','e' }; 
	 Q= initQueue(Q, 20);
	 printf("队列初始化成功!\n"); 
	 bool a= isEmpty(Q); 
	 if (a) printf("队列为空!\n"); 
	 for (int i = 0; i < 10; i++)
	 {
		 add(Q, arr[i]); 
	 }
	 printf("元素已入队\n"); 
	 printf("队列中有%d个元素 \n", count(Q)); 
	 printf("出队元素: %c\n" ,  Dequeue(Q)) ;
	 printf("队列中有%d个元素 \n", count(Q));
	 for (int i = 10; i < 14; i++)
	 {
		 add(Q, arr[i]);
	 }
	 queueTravel(Q); 


 }

题目练习

  1. 一个顺序存储的循环队列最大能存储的元素数目是100,如果设队头指针(约定为指向队头元素前一位置)和队尾指针的值分别是13和89,那么队列中实际存储元素的个数是____;
    若队头指针和队尾指针的值分别是89和13,那么队列中实际存储元素的个数是____。

按照以上公式:
队头小于队尾的时候,将队尾减队头得到 76
队头大于队尾的是偶,有rear-head+maxsize
得到76 , 25。这里有个坑: 就是最大存储元素是100的话,实际上数组的长长度将是101。(要注意题意!)

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