系列文章目录
前言
本篇文章将讲到队列的基本概念,队列的顺序存储,以及队列的链式存储。
一、队列的基本概念
队列是一种特殊的受限制的线性表。
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出的t(First In First Out)的线性表,简称FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作!假设队列是q=(a1,a2,……,an),那么a1就是队头元素,而an是队尾元素。这样我们就可以删除时,总是从a1开始,而插入时,总是在队列最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然排在队伍最后。
二、队列的顺序结构
- dynamicArray.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//动态数组结构体
struct dynamicArray
{
void ** pAddr; //维护真实在堆区创建的数组的指针
int m_capacity; // 数组容量
int m_size; //数组大小
};
//初始化数组
struct dynamicArray * init_DynamicArray(int capacity);
//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data);
//遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*));
//删除数组 按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos);
//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *));
//销毁数组
void destroy_DynamicArray(struct dynamicArray* array);
- seqQueue.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "dynamicArray.h"
#define MAX 1024
typedef void* seqQueue;
//初始化队列
seqQueue init_SeqQueue();
//入队
void push_SeqQueue(seqQueue queue, void* data);
//出队
void pop_SeqQueue(seqQueue queue);
//返回队列大小
int size_SeqQueue(seqQueue queue);
//判断队列是否为空
int isEmpty_SeqQueue(seqQueue queue);
//返回队头元素
void* front_SeqQueue(seqQueue queue);
//返回队尾元素
void* back_SeqQueue(seqQueue queue);
//销毁队列
void destroy_SqeqQueue(seqQueue queue);
- dynamicArray.c
#include "dynamicArray.h"
//初始化数组
struct dynamicArray * init_DynamicArray(int capacity)
{
if (capacity <= 0)
{
return NULL;
}
//给数组分配空间
struct dynamicArray * array = malloc(sizeof(struct dynamicArray));
if (array == NULL)
{
return NULL;
}
//给数组初始化
array->pAddr = malloc(sizeof(void *)* capacity);
array->m_capacity = capacity;
array->m_size = 0;
return array;
}
//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
if (array == NULL)
{
return;
}
if (data == NULL)
{
return;
}
//无效位置 尾插
if (pos < 0 || pos > array->m_size)
{
pos = array->m_size;
}
//判断是否满了,如果满动态扩展
if (array->m_size == array->m_capacity)
{
//1、计算新空间大小
int newCapacity = array->m_capacity * 2;
//2、创建新空间
void ** newSpace = malloc(sizeof(void *)* newCapacity);
//3、将原有数据拷贝到新空间下
memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);
//4、释放原有内存空间
free(array->pAddr);
//5、更新新空间指向
array->pAddr = newSpace;
//6、更新新容量
array->m_capacity = newCapacity;
}
//插入新元素
//移动元素 进行插入新元素
for (int i = array->m_size - 1; i >= pos; i--)
{
//数据向后移动
array->pAddr[i + 1] = array->pAddr[i];
}
//将新元素 插入到指定位置上
array->pAddr[pos] = data;
//更新大小
array->m_size++;
}
//遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
if (array == NULL)
{
return;
}
if (myPrint == NULL)
{
return;
}
for (int i = 0; i < array->m_size; i++)
{
myPrint(array->pAddr[i]);
}
}
//删除数组 按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
if (NULL == array)
{
return;
}
if (pos < 0 || pos > array->m_size - 1)
{
return;
}
//数据前移
for (int i = pos; i < array->m_size - 1; i++)
{
array->pAddr[i] = array->pAddr[i + 1];
}
//更新数组大小
array->m_size--;
}
//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
if (array == NULL)
{
return;
}
if (data == NULL)
{
return;
}
for (int i = 0; i < array->m_size; i++)
{
if (myCompare(array->pAddr[i], data))
{
//如果找到要删除的数据,i就是要删除的具体位置
removeByPos_DynamicArray(array, i);
break;
}
}
}
//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
if (array == NULL)
{
return;
}
if (array->pAddr != NULL)
{
free(array->pAddr);
array->pAddr = NULL;
}
free(array);
array = NULL;
}
- seqQueue.c
#include "seqQueue.h"
//初始化队列
seqQueue init_SeqQueue()
{
struct dynamicArray* arr = init_DynamicArray(MAX);
return arr;
}
//入队
void push_SeqQueue(seqQueue queue, void* data)
{
//本质 尾插
if (queue == NULL)
{
return;
}
if (data == NULL)
{
return;
}
struct dynamicArray* myQueue = queue;
if (myQueue->m_size == MAX)
{
return;
}
insert_DynamicArray(myQueue, myQueue->m_size, data);
}
//出队
void pop_SeqQueue(seqQueue queue)
{
// 本质 头删
if (queue == NULL)
{
return;
}
struct dynamicArray* myQueue = queue;
if (myQueue->m_size <= 0)
{
return;
}
removeByPos_DynamicArray(myQueue, 0);
}
//返回队列大小
int size_SeqQueue(seqQueue queue)
{
if (queue == NULL)
{
return -1;
}
struct dynamicArray* myQueue = queue;
return myQueue->m_size;
}
//判断队列是否为空
int isEmpty_SeqQueue(seqQueue queue)
{
if (queue == NULL)
{
return -1;
}
struct dynamicArray* myQueue = queue;
if (myQueue->m_size == 0)
{
return 1;
}
return 0;
}
//返回队头元素
void* front_SeqQueue(seqQueue queue)
{
if (queue == NULL)
{
return NULL;
}
struct dynamicArray* myQueue = queue;
return myQueue->pAddr[0];
}
//返回队尾元素
void* back_SeqQueue(seqQueue queue)
{
if (queue == NULL)
{
return NULL;
}
struct dynamicArray* myQueue = queue;
return myQueue->pAddr[myQueue->m_size - 1];
}
//销毁队列
void destroy_SeqQueue(seqQueue queue)
{
if (queue == NULL)
{
return;
}
destroy_DynamicArray(queue);
}
- 队列顺序存储.c
#include "seqQueue.h"
struct Person
{
char name[64];
int age;
};
void test01()
{
//初始化队列
seqQueue myQueue = init_SeqQueue();
//准备数据
struct Person p1 = { "aaa", 10 };
struct Person p2 = { "bbb", 20 };
struct Person p3 = { "ccc", 30 };
struct Person p4 = { "ddd", 40 };
//入队
push_SeqQueue(myQueue, &p1);
push_SeqQueue(myQueue, &p2);
push_SeqQueue(myQueue, &p3);
push_SeqQueue(myQueue, &p4);
printf("队列大小为:%d\n", size_SeqQueue(myQueue));
while (isEmpty_SeqQueue(myQueue) == 0)
{
//访问队头
struct Person* pFront = front_SeqQueue(myQueue);
printf("队头元素 -- 姓名:%s 年龄: %d\n", pFront->name, pFront->age);
//访问队尾
struct Person* pBack = back_SeqQueue(myQueue);
printf("队尾元素 -- 姓名:%s 年龄: %d\n", pBack->name, pBack->age);
//出队
pop_SeqQueue(myQueue);
}
printf("队列大小为:%d\n", size_SeqQueue(myQueue));
//销毁队列
destroy_SeqQueue(myQueue);
}
int main() {
test01();
system("pause");
return EXIT_SUCCESS;
}
三、队列的链式存储
linkQueue.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// 结点结构体
struct QueueNode
{
struct QueueNode* next;
};
//队列结构体
struct LQueue
{
struct QueueNode pHeader;
int m_size;
struct QueueNode* pTail;
};
typedef void* LinkQueue;
//初始化队列
LinkQueue init_LinkQueue();
//入队
void push_LinkQueue(LinkQueue queue, void* data);
//出队
void pop_LinkQueue(LinkQueue queue);
//返回队列大小
int size_LinkQueue(LinkQueue queue);
//判断是否为空
int isEmpty_LinkQueue(LinkQueue queue);
//返回队头
void* front_LinkQueue(LinkQueue queue);
//返回队尾
void* back_LinkQueue(LinkQueue queue);
//销毁队列
void destroy_LinkQueue(LinkQueue queue);
linkQueue.c
#include "linkQueue.h"
//初始化队列
LinkQueue init_LinkQueue()
{
struct LQueue* myQueue = malloc(sizeof(struct LQueue));
if(myQueue == NULL)
{
return NULL;
}
myQueue->pHeader.next = NULL;
myQueue->m_size = 0;
myQueue->pTail = &myQueue->pHeader;
return myQueue;
}
//入队
void push_LinkQueue(LinkQueue queue, void* data)
{
if (queue == NULL)
{
return;
}
if (data == NULL)
{
return;
}
//本质 尾插
struct LQueue* myQueue = queue;
struct QueueNode* myNode = data;
//更新指针指向
myQueue->pTail->next = myNode;
myNode->next = NULL;
//更新新的尾结点
myQueue->pTail = myNode;
myQueue->m_size++;
}
//出队
void pop_LinkQueue(LinkQueue queue)
{
if (queue == NULL)
{
return;
}
struct LQueue* myQueue = queue;
//本质 头删
if (myQueue->m_size == 0)
{
return;
}
if (myQueue->m_size == 1)
{
myQueue->pHeader.next = NULL;
myQueue->pTail = &myQueue->pHeader; ///1个节点的时候,要将尾节点还原到头
}
//记录第一个有数据的节点
struct QueueNode* pFirst = myQueue->pHeader.next;
//更改指针指向
myQueue->pHeader.next = pFirst->next;
myQueue->m_size--;
}
//返回队列大小
int size_LinkQueue(LinkQueue queue)
{
if (queue == NULL)
{
return -1;
}
struct LQueue* myQueue = queue;
return myQueue->m_size;
}
//判断是否为空
int isEmpty_LinkQueue(LinkQueue queue)
{
if (queue == NULL)
{
return -1;
}
struct LQueue* myQueue = queue;
if (myQueue->m_size == 0)
{
return 1;
}
return 0;
}
//返回队头
void* front_LinkQueue(LinkQueue queue)
{
if (queue == NULL)
{
return NULL;
}
struct LQueue* myQueue = queue;
return myQueue->pHeader.next;
}
//返回队尾
void* back_LinkQueue(LinkQueue queue)
{
if (queue == NULL)
{
return NULL;
}
struct LQueue* myQueue = queue;
return myQueue->pTail;
}
//销毁队列
void destroy_LinkQueue(LinkQueue queue)
{
if (queue == NULL)
{
return;
}
free(queue);
queue = NULL;
}
队列的链式存储
#include "linkQueue.h"
struct Person
{
void* node;
char name[64];
int age;
};
void test01()
{
//初始化队列
LinkQueue myQueue = init_LinkQueue();
//准备数据
struct Person p1 = { NULL, "aaa", 10 };
struct Person p2 = { NULL, "bbb", 20 };
struct Person p3 = { NULL, "ccc", 30 };
struct Person p4 = { NULL, "ddd", 40 };
struct Person p5 = { NULL, "eee", 50 };
//入队
push_LinkQueue(myQueue, &p1);
push_LinkQueue(myQueue, &p2);
push_LinkQueue(myQueue, &p3);
push_LinkQueue(myQueue, &p4);
push_LinkQueue(myQueue, &p5);
printf("队列大小为:%d\n", size_LinkQueue(myQueue));
while (isEmpty_LinkQueue(myQueue) == 0)
{
//访问队头
struct Person* pFront = front_LinkQueue(myQueue);
printf("链式存储::队头元素 -- 姓名:%s 年龄: %d\n", pFront->name, pFront->age);
//访问队尾
struct Person* pBack = back_LinkQueue(myQueue);
printf("链式存储::队尾元素 -- 姓名:%s 年龄: %d\n", pBack->name, pBack->age);
//出队
pop_LinkQueue(myQueue);
}
printf("队列大小为:%d\n", size_LinkQueue(myQueue));
//销毁队列
destroy_LinkQueue(myQueue);
}
int main() {
test01();
system("pause");
return EXIT_SUCCESS;
}
总结
到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦!