数据结构队列
- 队列的概念及结构
- 队列的是实现
- 数据结构
- 函数接口
- 初始化
- 销毁
- 入队列(尾插)
- 出队列(头删)
- 求队列的长度
- 判断队列是否为空
- 取队头的数据
- 取队尾的数据
队列的概念及结构
队列之允许在一段及进行数据插入操作,在另一端进行数据的删除操作的特殊线性表。队列具有先进先出(First In First Out)的特性
进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
队列的是实现
队列用数组和链表都可以实现,使用链表的结构实现更优一点,因为如果使用数组的结构,出队列在数组头上出数据,效率比较低。
数据结构
我们选择用链表实现,首先创建一个节点结构体QueueNode,在创建一个结构体来存队列的头节点指针和尾节点指针,这样入队和出队的效率会大大提高。
定义一个整型变量Size来存放队列的长度
代码:
typedef int QDataType;//数据类型
typedef struct QueueNode
{
struct Queue* next;//下一个节点
QDataType data;//数据
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
函数接口
void QueueInit(Queue* pq);//初始化
void QueueDestroy(Queue* pq);//销毁
void QueuePush(Queue*pq,QDataType x);//插入
void QueuePop(Queue* pq);//删除
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);//判断队列是否为空
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
初始化
空队列的头和尾节点都是NULL,比较简单
代码:
void QueueInit(Queue* pq)//初始化
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
销毁
直接逐步遍历链表然后逐步free
代码:
void QueueDestroy(Queue* pq)//销毁
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;//防止野指针的生成
pq->size = 0;
}
入队列(尾插)
队列的性质是先进先出,所以入队就是尾插,那么就简单了
1.只要是插入就要判断队列是否为空,若为空就需要改变头指针,让头指针指向新节点。
2.不为空直接将尾指针指向的节点连接新节点即可。
代码:
void QueuePush(Queue* pq,QDataType x)//插入(尾插)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc\n");
return;
}
newnode->data = x;//数据的写入
newnode->next = NULL;//因为是尾插 所以尾指针为NULL
if (pq->head == NULL)//如果插入前队列为空
{
assert(pq->tail == NULL);//如果head为空 tail不为空就有问题
pq->head = pq->tail = newnode;
}
else //插入前队列不为空
{
pq->tail->next = newnode;
pq->tail = pq->tail->next;//尾节点向后遍历
}
pq->size++;
}
出队列(头删)
出队列就相当于链表的头删,
1.头删要排除空队列的情况。
2.需要创建临时变量
3.当队列有一个元素的时候,删除后head为NULL但是tail为野指针,所以tail也需要置空。
代码:
void QueuePop(Queue* pq)//删除(头删)
{
assert(pq);
assert(pq->head);//空队列不能删除
QNode* cur = pq->head;
pq->head = pq->head->next;
free(cur);
cur = NULL;
pq->size--;
if (pq->head == NULL)//队列中只有一个元素删除了之后 head为NULL,但是此时tail为野指针
{
pq->tail = NULL;
}
}
求队列的长度
int QueueSize(Queue* pq)//求队列的长度
{
assert(pq);
return pq->size;
}
判断队列是否为空
bool QueueEmpty(Queue* pq)//判断队列是否为空
{
assert(pq);
return pq->size == 0;
}
取队头的数据
QDataType QueueFront(Queue* pq)//取队头的数据
{
assert(pq);
assert(!QueueEmpty(pq));//队列不为空
return pq->head->data;
}
取队尾的数据
QDataType QueueBack(Queue* pq) //取队尾的数据
{
assert(pq);
assert(!QueueEmpty(pq));//队列不为空
return pq->tail->data;
}