数据结构队列笔记
一、队列的结构
队列是先进先出的一种结构,出数据只能在从队头出,进数据只能从队尾进。
二、队列的实现
实现队列可以使用数组或者链表, 两种结构各有优劣。
使用链表实现队列
typedef int Quedatateype//定义队列数据类型
struct QueNode
{
QueNode*next;
Quedatatype x;
}
//此结构代表单个节点
第一个结构体代表单个节点,下面的结构体表示整个队列,使用时候构建结构体也是使用下面的结构体
// 队列的结构
typedef struct Queue
{
QNode* front; //指向头节点
QNode* rear; //指向尾节点
}Queue;
队列的增删查改
//初始化
void Queinit(Que* q)
{
q->data = NULL;
q->tail = NULL;
q->size = 0;
}
//插入数据
void QuePush(Que* q, Queuedata x)
{
assert(q);
Qnode* node = (Qnode*)malloc(sizeof(Qnode));
node->x = x;
node->next = NULL;
if (q->data == NULL)
{
q->data = q->tail = node;
}
else
{
q->tail->next = node;
q->tail = node;
}
q->size++;
}
//获取数据
Quedatateype rtQue(Que* q)
{
assert(q->size);
int ret = q->data->x;
return ret;
}
//数据个数
Quedatateype QueSize(Que* q)
{
assert(q);
return q->size;
}
//判断空队列
bool QueEmpty(Que* q)
{
return QueSize(q) == 0;
}
//删除数据
void QuePop(Que* q)
{
assert(q);
assert(!QueEmpty(q));
if (q->size == 1)
{
free(q->data);
q->data = NULL;
q->tail = NULL;
}
else
{
Qnode* next = q->data->next;
free(q->data);
q->data = next;
}
q->size--;
}
//释放队列
void QueFree(Que* q)
{
assert(q);
free(q->data);
free(q->tail);
q->size = 0;
free(q);
}
//获取队尾数据
Quedatateype QueBack(Que* q)
{
assert(q);
return q->tail->x;
}
三、循环队列的实现
循环队列是一种有限容量的,空间可以循环利用的队列,循环队列没有固定的头和尾,需要根据情况灵活判断因为空间的有限性,所以需要判断空间是否足够,判满有多种方式
1.在队列中加入一个变量size,如果size和容量则队列已满
2.在队列中多留一个空间作为未来要插入数据的位置,如果该空间的下一个是头节点,说明队列已满
代码实现循环队列
i由于循环队列的空间是有限的,所以我们使用数组来实现
typedef struct {
int *data;//数组
int rear;//尾部下标
int haed;//头下标
int k;//数组大小
} MyCircularQueue;
初始化循环队列
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*node=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
node->data=(int*)malloc(sizeof(int)*(k+1));
node->rear=0;
node->haed=0; 初始化时头尾下标为0
node->k=k;
return node;
}
队列判空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->haed==obj->rear;
}
队列判满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->k+1)==obj->haed;
}
插入数据
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
return false;
obj->data[obj->rear]=value;
obj->rear=(obj->rear+1)%(obj->k+1);
return true;
}
删除数据
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return false;
obj->haed=(obj->haed+1)%(obj->k+1);
return true;
}
出数据
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->data[obj->haed];
}
返回尾部数据
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->data[(obj->rear+obj->k)%(obj->k+1)];
}
释放队列
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->data);
free(obj);
}