循环队列的简单知识

队列其实也是链表,这里讲的是顺序表示。队列,顾名思义,就是排队的队形。按照专业一点就是FIFO(first in first out) 原则,从对列头出列,从对尾入列。

因为循环队列最利用效率,也稍微增加了难度,所以要记住循环队列的表示方法。

其实很多数据结构都有很多种写法,重要是理解其思想,代码完成只是让自己更加透彻的掌握,每一种实现方式都是按其思想一步一步完成的。

先贴出结构体:

typedef struct queue {

         int*Base;//数组头指针

         int front;//对头

         int rear;//队尾。。实际就是数组下标

         int size;//队列长度

}Queue;

如果不同的数据类型 int *Base 的类型记得换,还有好多地方 ,记得就行了。

之所以用循环队列,是因为对头只能出,对尾只能入,这样就变成了上面的位置空出后就一直空着了,造成了很大的浪费啊。

我之前学的时候循环队列的时候就觉得很晕,主要是当时我的确太渣了,现在理解了其中的道理,感觉还是挺好玩的。循环的意思并没有违背对头对尾的概念,就像我在一个圆圈上开了俩个洞,一个标为头,一个标为尾,所以不管转或不转,我的标志就在那儿。

我们这样想,假如这个循环的圈圈,有6个位置,但是我们只装5个数(代码有注释),

e→ d →c →b→ a    头

↑                             |

 ————————

下标是 4 3 2 1 0等到装满的时候便不能装了,然后出对是不,那么这时候a下标为0从头出去了,那么对头就变成

q->front = (q->front+1) % q->size;

成为了1,然后有数f来入队,那么此时对尾变成了

q->rear = (q->rear +1)% q->size;

成为了0,看到了没,就因为简单的取余的操作,我的下标永远在0-4间循环,就成为了循环队列。

好了,也许和我当初学的时候想的不一样,以后还是觉得把刚学的知识,马上写出感受才好,新鲜又贴近最真实的感觉。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef struct queue {

	int *Base;//数组头指针
	int front;//对头
	int rear;//队尾。。实际就是数组下标
	int size;//队列长度
}Queue;

void InitQueue(Queue *q, int size) {
	q->size = size;
	q->Base = (int *)malloc(sizeof(int)*q->size);//分配内存空间
	if(NULL == q->Base) {
		printf("failed!\n");
		exit(-1);
	}
	q->front = 0;
	q->rear = 0;//初始化队列里没有元素 下标为0
}

void DestroyQueue(Queue *q) {
	q->front = 0;
	q->rear = 0;
	q->size = 0;
	free(q->Base);//回收空间
	q->Base = NULL;
}

void clearQueue(Queue *q) {
	q->front = 0;
	q->rear = 0;
}

bool isEmpty(Queue *q) {
	if(q->front == q->rear ) {//空队列里面肯定头尾在一起
		printf("empty!\n");
		return true;
	}else
		return false;


}
bool isFull(Queue *q) {
	if((q->rear+1)%q->size == q->front) {
		// 循环队列当取余头尾相等时代表队列已满,+1代表空余一个就表示已满否则取余就无意思
		printf("Full!\n");
		return true;
	}
	else
		return false;
}
bool getHead(Queue *q, int *e) {

	if(isEmpty(q)) {
		printf("no head element\n");
		return false;
	}else {
		*e = q->Base[q->front];
		printf("the head is :%d\n ",*e);
		return true;
	}
}

int length(Queue *q) {
	return (q->rear - q->front +q->size) % q->size;
//	return (q->rear - q->front ) % q->size;//这样容易造成长度为负数(因为是循环队列 对头队尾不知道那个比较大)
}
//出对入队只要记着队尾入队,对头出对即可。
bool enQueue(Queue *q, int item) {
	if(isFull(q)){
		return false;
	}
	else {
		q->Base[q->rear] = item;
		q->rear = (q->rear +1)% q->size;
	
	}
	return true;
}
bool deQueue(Queue *q, int *item) {
	if(isEmpty(q)) 
		return false;
	else {
		*item = q->Base[q->front];
		q->front = (q->front+1) % q->size;
	}

	return true;
}
//测试程序
int main() {
	int temp;

	Queue q;
	InitQueue(&q,5);
	printf("%d\n",isEmpty(&q));
	
	enQueue(&q,1);
	deQueue(&q,&temp);
	enQueue(&q,2);
	enQueue(&q,8);
	deQueue(&q,&temp);
	enQueue(&q,18);
	enQueue(&q,3);
	deQueue(&q,&temp);
	enQueue(&q,4);
	enQueue(&q,5);

		printf("the length:%d \n",length(&q));

int a;
	getHead(&q,&a);

	for(int i =1 ;i <=4; i++) {
		int item; 
		deQueue(&q,&item);
		printf("%d ",item);
	}
	DestroyQueue(&q);//队列已经销毁 任何操作都没用了
	//enQueue(&q,1);
	getHead(&q,&a);

	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值