【数据结构与算法】受限线性表-队列

系列文章目录


前言

本篇文章将讲到队列的基本概念,队列的顺序存储,以及队列的链式存储。


一、队列的基本概念

队列是一种特殊的受限制的线性表。
队列(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;
}

总结

到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值