队列,及队列的模拟实现,循环队列

一、队列

(1)队列的概念及结构

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

 队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。

头文件部分:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct QNode//构建一个结构体,用于创建每一个结点
{
	QDataType val;
	struct QNode* next;
}QNode;
typedef struct Queue//创建一个结构体,表示队列的头和尾
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;
//初始化
void QInit(Queue* pq);
//销毁
void QDestroy(Queue* pq);
//插入
void QPush(Queue* pq, QDataType x);
//删除
void QPop(Queue* pq);
//队头的数据
QDataType QFront(Queue* pq);
//队尾的数据
QDataType QBack(Queue* pq);
//判断是否为空
bool QEmpty(Queue* pq);
//队列的大小
size_t Qsize(Queue* pq);

函数的实现部分:

#include"Queue.h"
//初始化
void QInit(Queue* pq) //初始化的时候有不同的方法,可以先给顺序表先开辟一定的空间
//当开辟一定空间了后,在后面的插入的部分,就可以不必判定顺序表是否为空
{
	assert(pq);
	//检查pq是否为空指针,因为当pq为指针了后,后面的语句要对pq进行运用,就会存在对空指针的调用--即野指针的问题
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}
//销毁
void QDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;
		free(del);
	}
	pq->head = pq->tail = NULL;  //防止野指针的访问
	pq->size = 0;
}
//判断是否为空
bool QEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL && pq->tail == NULL;
}
//插入
void QPush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* new = (QNode*)malloc(sizeof(QNode));//开辟一个新的点,用来存放要插入的值--x
	if (new == NULL)//检查机制,因为malloc可能没有开辟空间
	{
		perror("malloc fail");//当没有开辟的时候,给我们报错,说明空间没有开辟成功
		exit(-1);
	}
	new->val = x;
	new->next = NULL;
	//当队列原本没有数据时,即size = 0;
	if (pq->head == NULL)
	{
		pq->head = pq->tail = new;
	}
	else
	{
		pq->tail->next = new;
		pq->tail = new;
	}
	pq->size++;
}
//删除
void QPop(Queue* pq)
{
	assert(pq);
	assert(!QEmpty(pq));//当顺序表为空的时候,不能进行删数据
	if (pq->head->next == NULL)//当只存在一个数据的时候
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* del = pq->head;
		pq->head = pq->head->next;
		free(del);
	}
	pq->size--;
}
//队头的数据
QDataType QFront(Queue* pq) 
{
	assert(pq);
	assert(pq->head != NULL);
	return pq->head->val;
}
//队尾的数据
QDataType QBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail != NULL);
	return pq->tail->val;
}
//队列的大小
size_t Qsize(Queue* pq)
{
	//在构建顺序表的时候,如果我们没有设定一个size来进行对插入删除的统计时,就采用第二种方法
	assert(pq);
	return pq->size;
	//(2)
	//int count = 0;
	//QNode* cur = pq->head;
	//while (cur)
	//{
	//	count++;
	//	cur = cur->next;
	//}
	//return count;
}

循环队列:

可以用链表来进行实现,也可以用数组进行实现。

此时实现以数组的方式:

typedef struct
{
    int front;//指向第一个元素
    int rear;//指向最后一个元素的下一个位置
    int capacity;//数组的大小
    int *elements;//开辟的数组
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue *obj = (MyCircularQueue *)malloc(sizeof(MyCircularQueue));
    obj->capacity = k + 1;//多开一个空间,解决判满的问题
    obj->rear = obj->front = 0;//当数据满了的时候,总的大小应该是k+1
    obj->elements = (int *)malloc(sizeof(int) * obj->capacity);
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
    if ((obj->rear + 1) % obj->capacity == obj->front) 
    { //当空间满了后不能继续插入
        return false;
    }
    obj->elements[obj->rear] = value;
    obj->rear = (obj->rear + 1) % obj->capacity;//更新rear的位置
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
    if (obj->rear == obj->front) //当没有元素的时候不能进行删除
    {
        return false;
    }
    obj->front = (obj->front + 1) % obj->capacity;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if (obj->rear == obj->front) //没有元素的时候
    {
        return -1;
    }
    return obj->elements[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) 
{
    if (obj->rear == obj->front) 
   {
        return -1;
    }
    return obj->elements[(obj->rear - 1 + obj->capacity) % obj->capacity];
    //通过rear的位置来寻找最后一个元素的位置
}

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

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    return (obj->rear + 1) % obj->capacity == obj->front;
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
    free(obj->elements);
    free(obj);
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山野村夫.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值