数据结构--队列及循环队列实现

队列:

队列和栈一样也是一种,但是他与栈不同的是在一段插入数据,在另一端删除数据。
在这里插入图片描述

队列基本操作是入队(enqueue),以及出队(dequeue),入队在表的队尾(rear)插入元素,出队是在队头(front)删除或返回一个元素。

队列和栈一样都可以用任何表来实现,本文选择用链表实现队列。

队列结构:

typedef int DataType;

typedef struct QueueNode {
	DataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;//定义头和尾

队列接口函数:

void QueueInit(Queue* pq);//队列初始化
void QueueDestory(Queue* pq);//销毁队列
void QueuePush(Queue* pq, DataType x);//入队
void QueuePop(Queue* pq);//出队
bool QueueEmpty(Queue* pq);//队列是否为空
size_t QueueSize(Queue* pq);//队列元素
DataType QueueFront(Queue* pq);//头元素
DataType QueueBack(Queue* pq);//尾元素

队列初始化与销毁:

void QueueInit(Queue* pq) {
	assert(pq);
	pq->head = pq->tail = NULL;
}//初始化
void QueueDestory(Queue* pq) {
	assert(pq);
	QNode* cur = pq->head;
	while (cur) {//对每一个元素进行free
		QNode* next = cur->next;
		free(cur);
		cur = cur->next;
	}
	pq->head = pq->tail = NULL;
}//销毁

出队和入队:

void QueuePush(Queue* pq, DataType x) {
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	assert(newnode);

	newnode->data = x;
	newnode->next = NULL;

	if (pq->tail == NULL) {//当无任何元素时
		assert(pq->head == NULL);
		pq->head = pq->tail = newnode;
	}
	else {
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}//入队
void QueuePop(Queue* pq) {
	assert(pq);
	assert(pq->head && pq->tail);

	if (pq->head->next == NULL)//当只有对头元素时
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

其他函数:

bool QueueEmpty(Queue* pq) {
	return pq->head == NULL;
}//判断是否为空
size_t QueueSize(Queue* pq) {
	assert(pq);

	QNode* cur = pq->head;
	size_t size = 0;
	while (cur)
	{
		size++;
		cur = cur->next;
	}

	return size;
}//返回队列元素数量
DataType QueueFront(Queue* pq) {
	assert(pq);
	assert(pq->head);

	return pq->head->data;
}//返回对头元素
DataType QueueBack(Queue* pq) {
	assert(pq);
	assert(pq->tail);

	return pq->tail->data;
}//返回队尾元素

测试函数:

#include"Queue.h"

void Test1() {
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);

	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");
}
int main() {
	Test1();
	return 0;
}

在这里插入图片描述

循环队列:

由于队列需要不断的增减元素,为了减少空间浪费可以采用循环队列,其结构如图所示。

在这里插入图片描述

力扣连接:设计循环队列

创建一个数组,数组大小一定,定义一个头和尾。

front表示队头,tail表示队尾,进入一个元素tail++,删除一个元素时front++。

而因为不管队列为满或为空时front都等于tail,所以无法区分队列何时为空何时为满,为此加入一个空元素,此时可以区分出空和满的情况。

当front+1 == tail时表示循环链表为满,当tail == front 时表示数组为空。

typedef struct {
   int* a;
   int front;
   int tail;
   int k;
} MyCircularQueue;

bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);


MyCircularQueue* myCircularQueueCreate(int k) {
   MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
   
   obj->a =(int*) malloc(sizeof(int)*(k + 1));//要存储k个元素就需要k+1份空间
   obj->front = obj->tail = 0;
   obj->k = k;

   return obj;
}//初始化队列

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj)) {
        return false;
    }

    obj->a[obj->tail] = value;
    if (obj->tail == obj->k) {
        obj->tail = 0;
    }//当tail == k时也就是tail走到最后一位时需要退回到第一位
    else {
        obj->tail++;
    }

    return true;

}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)){
        return false;
    }

    if (obj->front == obj->k) {
        obj->front = 0;
    }//front走到k时需要退回到0处
    else {
        obj->front++;
    }
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) {
        return -1;
    }
    if (obj->tail == 0){
        return obj->a[obj->k];
    }//如果tail在0处时队尾元素在k位置处
    else{
        return obj->a[obj->tail - 1];
    }
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj){
    return obj->front == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj){
    if(obj->tail == obj->k && obj->front == 0) { 
        return true;
    }
    else{
        return obj->tail + 1 == obj->front;
    }
}

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值