前言:在实现栈之后我们再介绍一下他的孪生兄弟,一个是后进先出,一个是先进先出。那么就让我们来详细的了解一下队列把。
目录
一.队列概念
队列:
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在数组内实现避免不了有数据的移动,比如将a0当队头插入队列时进行尾插,但是在每次出队的时候需要将后面的数据向前移动一位,这就不免是(n-1)的时间复杂度。
而将an做位队头那么每次插入时又需要挪动数据,时间复杂度也是(n-1),所以我们采用链表的方式实现就很方便。
二.队列的实现
1.定义队列
cpp
typedef int QEtype;
typedef struct QEnode{
QEtype val;
struct QEnode *next;
}QEnode;
typedef struct QE
{
QEnode* head;
QEnode* tail;
int size;
}QE;
这里我们把队列的队头,队尾以及队列的长度记录下来。这样会对我们进行的操作有很大的便利。
2.初始化队列
cpp
void QEInit(QE* qe)
{
assert(qe);
qe->head = NULL;
qe->tail = NULL;
qe->size = 0;
}
3.入队
cpp
void QEPush(QE* qe, QEtype x)
{
assert(qe);
QEnode* newnext = (QEnode*)malloc(sizeof(QEnode));
if (newnext == NULL)
{
perror(malloc);
return;
}
newnext->next = NULL;
newnext->val = x;
if (qe->size == 0)
{
qe->head = qe->tail = newnext;
}
else
{
qe->tail->next = newnext;
qe->tail = newnext;
}
qe->size++;
}
我们入队列选用的是尾插。
4.判断队列是否为空
cpp
_Bool QEempty(QE* qe)
{
assert(qe);
return qe->size == 0;
}
5.出队
cpp
void QEPop(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
if (qe->size == 1)
{
free(qe->head);
qe->head = NULL;
qe->tail = NULL;
}
else
{
QEnode* prev = qe->head->next;
free(qe->head);
qe->head = prev;
}
qe->size--;
}
对于出队我们选用头删。
6.返回队头和队尾
cpp
QEnode* QETop(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->head;
}
QEnode* QEDown(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->tail;
}
这就是我们当时表示出来队头和队尾的方便之处。
7.查看队尾内容
cpp
QEtype ShowDown(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->tail->val;
}
8.查看队列数量
cpp
int QESize(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->size;
}
9.销毁队列
cpp
void QEDestory(QE* qe)
{
assert(qe);
qe->head = qe->tail = NULL;
qe->size = 0;
free(qe->head);
free(qe->tail);
}
三.队列实现所有代码
cpp
QE.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QEtype;
typedef struct QEnode{
QEtype val;
struct QEnode *next;
}QEnode;
typedef struct QE
{
QEnode* head;
QEnode* tail;
int size;
}QE;
void QEInit(QE* qe);
void QEPush(QE* qe, QEtype x);
void QEPop(QE* qe);
_Bool QEempty(QE* qe);
QEnode* QETop(QE* qe);
QEnode* QEDown(QE* qe);
QEtype ShowDown(QE* qe);
int QESize(QE* qe);
void QEDestory(QE* qe);
QE.c
void QEInit(QE* qe)
{
assert(qe);
qe->head = NULL;
qe->tail = NULL;
qe->size = 0;
}
void QEPush(QE* qe, QEtype x)
{
assert(qe);
QEnode* newnext = (QEnode*)malloc(sizeof(QEnode));
if (newnext == NULL)
{
perror(malloc);
return;
}
newnext->next = NULL;
newnext->val = x;
if (qe->size == 0)
{
qe->head = qe->tail = newnext;
}
else
{
qe->tail->next = newnext;
qe->tail = newnext;
}
qe->size++;
}
_Bool QEempty(QE* qe)
{
assert(qe);
return qe->size == 0;
}
void QEPop(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
if (qe->size == 1)
{
free(qe->head);
qe->head = NULL;
qe->tail = NULL;
}
else
{
QEnode* prev = qe->head->next;
free(qe->head);
qe->head = prev;
}
qe->size--;
}
QEnode* QETop(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->head;
}
QEnode* QEDown(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->tail;
}
QEtype ShowDown(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->tail->val;
}
int QESize(QE* qe)
{
assert(qe);
assert(!QEempty(qe));
return qe->size;
}
void QEDestory(QE* qe)
{
assert(qe);
qe->head = qe->tail = NULL;
qe->size = 0;
free(qe->head);
free(qe->tail);
}
test.c
#include"QE.h"
void test()
{
QE qe = {0};
QEInit(&qe);
QEPush(&qe, 1);
QEPush(&qe, 2);
QEPush(&qe, 3);
QEPush(&qe, 4);
printf("队列数量%d\n", QESize(&qe));
while (!QEempty(&qe))
{
QEnode* ret = QETop(&qe);
printf("%d ", ret->val);
QEPop(&qe);
}
printf("\n队列数量%d", QESize(&qe));
}
int main()
{
test();
return 0;
}
四.结言
好了我么队列和栈就以及全部说完了,感谢大家的关注。
有喜欢的兄弟们可以一键三连!!
谢谢大家了,拜拜。