本次代码注释的很详细,需要解释的都在代码里了。
数据结构和算法->关于队列的使用
头文件:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int DATATYPE;
typedef struct Queue
{
struct Queue* next; //队列之间的元素使用指针连接起来
DATATYPE data;
}Queue;
typedef struct QueuePointer
{
//struct QueuePointer* head; //指向队列的第一个元素
//struct QueuePointer* tail; //指向队列的最后一个元素
Queue* head;
Queue* tail;
}QP;
//队列的初始化
void QueueInit(QP* phead);
//队列的插入
void QueuePush(QP* phead, DATATYPE X);
//队列的删除
void QueuePop(QP* phead);
//队列的输出
void QueuePrint(QP* phead);
//返回队列的队头的元素
DATATYPE QueueReturnFront(QP* phead);
//返回队列的队尾的元素
DATATYPE QueueRrturnBack(QP* phead);
//判断队列的元素个数
int QueueSize(QP* phead);
//判断队列是否为空
bool QueueEmpty(QP* phead);
//队列的销毁
void QueueDestroy(QP* phead);
源文件:
源文件包含两个,一个是主函数,程序的入口,包括函数的调用;另一个程序的执行代码,包括函数的定义。
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
//队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
//入队列:进行插入操作的一端称为队尾
//出队列:进行删除操作的一端称为队头
//队列也可以数组和链表的结构实现
//使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低
void queueTest1()
{
QP qp1;
QueueInit(&qp1);
QueuePush(&qp1, 1);
QueuePush(&qp1, 2);
QueuePush(&qp1, 3);
QueuePush(&qp1, 4);
QueuePrint(&qp1);
QueuePop(&qp1);
QueuePop(&qp1);
QueuePop(&qp1);
QueuePush(&qp1, 1);
QueuePush(&qp1, 2);
QueuePush(&qp1, 3);
QueuePrint(&qp1);
QueueDestroy(&qp1);
}
queueTest2()
{
QP qp2;
QueueInit(&qp2);
QueuePush(&qp2, 10);
QueuePush(&qp2, 20);
QueuePush(&qp2, 30);
QueuePush(&qp2, 40);
QueuePrint(&qp2);
DATATYPE temp = QueueReturnFront(&qp2);
printf("队头的元素是%d\n", temp);
DATATYPE ret = QueueRrturnBack(&qp2);
printf("队尾的元素是%d\n", ret);
if (QueueEmpty(&qp2))
{
printf("队列的大小是%d\n", QueueSize(&qp2));
}
else
{
printf("队列为空\n");
}
QueueDestroy(&qp2);
}
int main()
{
queueTest1();
queueTest2();
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
//队列的初始化
void QueueInit(QP* phead)
{
assert(phead);
phead->head = NULL;
phead->tail = NULL;
}
//队列的插入
void QueuePush(QP* phead, DATATYPE X)
{
assert(phead);
Queue* NewNode = (Queue*)malloc(sizeof(Queue));
if (NewNode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
NewNode->data = X;
NewNode->next = NULL;
if (phead->tail == NULL)
{
phead->head = phead->tail = NewNode;
}
else
{
phead->tail->next = NewNode;
phead->tail = NewNode;
}
}
//队列的删除
void QueuePop(QP* phead)
{
assert(phead);
assert(phead->head); //
if (phead->head->next == NULL)
{
free(phead->head);
phead->head = NULL;
phead->tail = NULL;
}
else
{
Queue* plist = phead->head->next;
free(phead->head);
phead->head = plist;
}
}
//返回队列的队头的元素
DATATYPE QueueReturnFront(QP* phead)
{
assert(phead);
assert(phead->head);
return phead->head->data;
}
//返回队列的队尾的元素
DATATYPE QueueRrturnBack(QP* phead)
{
assert(phead);
assert(phead->head);
return phead->tail->data;
}
//判断队列的元素个数
int QueueSize(QP* phead)
{
int count = 0; //一定要赋值,否则出现未定义行为
Queue* ptr_queue = phead->head;
while (ptr_queue)
{
count++;
ptr_queue = ptr_queue->next;
}
return count;
}
//判断队列是否为空
bool QueueEmpty(QP* phead)
{
return phead->head != NULL; //如果队列有元素,返回真,否则,返回假
}
//队列的输出
void QueuePrint(QP* phead)
{
Queue* plist = phead->head;
while (plist)
{
//printf("%d->", phead->head->data);
phead->head++; 链表的地址是不连续的
//phead->head = phead->head->next;//不要这样书写,这样改变了头指针的位置,会导致在调用的时候引起其他函数出现问题
printf("%d->", plist->data);
plist = plist->next;
}
printf("\n");
}
//队列的销毁
void QueueDestroy(QP* phead)
{
assert(phead);
//assert(phead->head); phead->head = NULL就表明目前没有开辟的内存空间,这里不需要断言
Queue* plist = phead->head;
while (plist)
{
//第一种写法:
//Queue* slist = plist->next;
Queue* slist = phead->head->next; //这样写是不行的,因为slist的位置没有改变
//free(plist);
//plist = slist->next;
//第二种写法:
plist = plist->next;
free(phead->head);
phead->head = plist;
}
phead->head = phead->tail = NULL;
}