队列的实现与运用(设计循环队列)

定义

队列是只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头

实现

队列可以数组和链表的结构实现,使用链表的结构实现好一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低在这里插入图片描述

代码

此处我们使用链表实现一个支持动态增长的栈

Queue.h

#include<stdio.h>
#include<string.h>
#include<assert.h>
typedef int DataType;
typedef struct QueueNode
{
	DataType _data;
	struct QueueNode* _next;
}QueueNode;

typedef struct Queue
{
	QueueNode* _front; // 队头
	QueueNode* _rear; // 队尾
}Queue;
void QueueInit(Queue* q);//初始化
void QueueDestroy(Queue* q);//销毁
void QueuePush(Queue* q, DataType x);//插入
void QueuePop(Queue* q);//删除
DataType QueueFront(Queue* q);//返回队头元素
DataType QueueBack(Queue* q);//返回队尾元素
int QueueEmpty(Queue* q);//判空
int QueueSize(Queue* q);//计算长度
void QueuePrint(Queue* q);//输出

Queue.c

#include "Queue.h"
//队列
void QueueInit(Queue* q)//初始化
{
	assert(q);
	q->_front = NULL;
	q->_rear = NULL;
}

void QueueDestroy(Queue* q)//销毁
{
	assert(q);
	QueueNode* cur = q->_front;
	while (cur)
	{
		QueueNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	q->_front = q->_rear = NULL;
}
void QueuePush(Queue* q, DataType x)//插入
{
	assert(q);
	QueueNode* newNode = (Queue*)malloc(sizeof(QueueNode));
	newNode->_data = x;
	newNode->_next = NULL;
	if (q->_front == NULL)
	{
		q->_front = q->_rear = newNode;
	}
	else
	{
		q->_rear->_next = newNode;
		q->_rear = q->_rear->_next;
	}
}
void QueuePop(Queue* q)//删除
{
	assert(q);
	if (q->_front)
	{
		QueueNode* next = q->_front->_next;
		free(q->_front);
		q->_front = next;
		if (q->_front == NULL)
			q->_rear = NULL;
	}
}

DataType QueueFront(Queue* q)//返回队头元素
{
	assert(q);
	if (q->_front)
		return q->_front->_data;
	return -1;
}
DataType QueueBack(Queue* q)//返回队尾元素
{
	assert(q);
	if (q->_rear)
		return q->_rear->_data;
	return -1;
}

int QueueEmpty(Queue* q)//判空
{
	assert(q);
	if (q->_front == NULL)
		return 1;
	else
		return 0;
}

int QueueSize(Queue* q)//计算长度
{
	int n = 0;
	QueueNode* cur = q->_front;
	while (cur)
	{
		++n;
		cur = cur->_next;
	}
	return n;
}
void QueuePrint(Queue* q)//输出
{
	assert(q);
	QueueNode* cur = q->_front;
	while (cur)
	{
		printf("%d ", cur->_data);
		cur = cur->_next;
	}
	printf("\n");
}
void test()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);

	QueuePrint(&q);
	QueueDestroy(&q);
}

int main()
{
	test();
	return 0;
}

运用

设计循环队列

循环队列是一种线性数据结构,其操作表现基于先进先出原则,并且队尾被连接在队首之后以形成一个循环,即环形缓冲器
循环队列的关键在于模拟循环,处理数组边界

typedef struct {
    int *data;
    int head;
    int tail;
    int cap;
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) //设置队长k 
{
    MyCircularQueue *queue = (MyCircularQueue *)malloc(sizeof(MyCircularQueue));
    queue -> data = (int *)malloc((k + 1) * sizeof(int)); //模拟动态数组,留出一位空闲
    queue -> head = 0;
    queue -> tail = 0;
    queue -> cap  = k + 1; 
    return queue;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) //判空
{
  if(obj -> head == obj -> tail)
  {
      return true;
  }
    return false;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) //判满
 {
  if(obj -> head == (obj -> tail + 1) % (obj -> cap))
  {
      return true;
  }
  return false;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)//插入
{
    if(myCircularQueueIsFull(obj) == true)
    {
        return false;
    }
    obj -> data[obj -> tail] = value;//First In
    obj -> tail = (obj -> tail + 1) % (obj -> cap); //索引 + 1,并且要注意取模计算,实现循环队列
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj)//删除
{
    if(myCircularQueueIsEmpty(obj) == true)
    {
        return false;
    }
    obj -> head = (obj -> head + 1) % (obj -> cap);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj)// 从队首获取元素
{
    if(myCircularQueueIsEmpty(obj) == true)
    {
        return -1;
    }
    else
    {
        return obj ->data[obj -> head];   
    }
}

int myCircularQueueRear(MyCircularQueue* obj) // 从队尾获取元素
{
    if(myCircularQueueIsEmpty(obj) == true)
    {
        return -1;
    }
    return obj -> data[(obj-> tail - 1 + obj -> cap) % (obj -> cap)]; //注意处理
}
void myCircularQueueFree(MyCircularQueue* obj)//销毁
{
    free(obj -> data);
    obj -> data = NULL;
    free(obj);
    obj = NULL;
}
发布了47 篇原创文章 · 获赞 108 · 访问量 4730

猜你喜欢

转载自blog.csdn.net/qq_44759710/article/details/104289213