【数据结构系列】队列的基本操作及实现

本文深入探讨了队列数据结构的两种主要实现方式:顺序队列和链队列。通过详细的代码示例,讲解了队列的基本操作,包括创建、入队、出队和遍历。特别关注了循环队列解决假溢出问题的方法,以及链队列的灵活应用。

DATE:2020.4.21


1、队列的定义

队列是一种特殊的线性表,特殊在于队列限定在一端进行插入,在另一端进行删除。
队列有两种物理存储结构:
1、顺序队列:循环队列是为了解决队列的“假溢出”现象。
2、链队列:队列的链式存储

2、队列的基本操作(创建、入队、出队、遍历)

#include <stdio.h>
#include <stdlib.h>

#define MAX_DATA_SIZE (20)
typedef int QElemType;

// 1、循环队列的顺序存储结构
typedef struct SqQueue
{
	QElemType data[MAX_DATA_SIZE];
	int front;  // 头指针 
	int rear;   // 尾指针,若队列不空,则指向队列尾元素的下一个位置
} SqQueue;

// 1.1、初始化一个空队列Q
int InitQueue(SqQueue *Q)
{
	Q->front = 0;
	Q->rear = 0;
	return 0;
}

// 1.2、返回队列Q中的元素个数
int GetLengthQueue(SqQueue *Q)
{
	return ((Q->rear - Q->front +  MAX_DATA_SIZE) % MAX_DATA_SIZE);
}

// 1.3、入队列:若队列未满,则插入元素e为Q新的队尾元素
int EnterQueue(SqQueue *Q, QElemType e)
{
	if ((Q->rear + 1) % MAX_DATA_SIZE == Q->front)
	{
		printf("队列满了,无法插入新元素!\n");
		return -1;
	}

	Q->data[Q->rear] = e;
	Q->rear = (Q->rear + 1) % MAX_DATA_SIZE;

	return 0;
}

// 1.4、出队列:若队列不空,则删除队头元素,并用e返回其值
int DeQueue(SqQueue *Q, int *e)
{
	if (Q->rear == Q->front)
	{
		printf("空栈!\n");
		return -1;
	}
	*e = Q->data[Q->front];
	Q->front =  (Q->front+1) % MAX_DATA_SIZE;

	return 0;
}


// 2、队列链式存储结构
typedef struct Node
{
	QElemType data;
	struct Node *next;
} Node, *LinkListPtr;

typedef struct LinkQueue
{
	LinkListPtr front, rear;
} LinkQueue;

// 2.1 队列初始化为空队列
int InitLinkQueue(LinkQueue *LQ)
{
	LinkListPtr QueueHead;
	QueueHead = (LinkListPtr) malloc(sizeof(Node));
	if (NULL == QueueHead)
	{
		printf("QueueHead malloc error!\n");
		return -1;
	}
	QueueHead->next = NULL;

	LQ->front = QueueHead;
	LQ->rear = QueueHead;

	return 0;
}

// 2.2 返回队列长度:遍历整个链表
int GetLengthLinkQueue(LinkQueue *LQ)
{
	LinkListPtr front = NULL;
	int length = 0;
	front = LQ->front;

	while (front != LQ->rear)
	{
		front++;
		length++;
	}
	return length;
}

// 2.3 入队操作:在链表尾部插入结点,对于链队列不存在满的情况
int EnterLinkQueue(LinkQueue *LQ, int ele)
{
	LinkListPtr newNode = (LinkListPtr) malloc(sizeof(Node));
	if (NULL == newNode)
	{
		printf("newNode malloc error!\n");
		return -1;
	}
	newNode->data = ele;

	newNode->next = NULL;		
	LQ->rear->next = newNode;
	LQ->rear = newNode;			// 类似链表的尾插法

	return 0;
}

// 2.4 出队操作:若队列非空,则将链表中第一个结点删除,并返回其值给ele
int DeleteLinkQueue(LinkQueue *LQ, int *ele)
{
	LinkListPtr Linkfront;
	if (LQ->front == LQ->rear)
	{
		printf("空队列!\n");
		return -1;
	}
	
	Linkfront = LQ->front->next;
	*ele = Linkfront->data;

	LQ->front->next = Linkfront->next;

	if (LQ->rear == Linkfront)
	{
		LQ->rear = LQ->front;
	}
	free(Linkfront);
	Linkfront = NULL;

	return 0;
}

// 2.5 遍历输出队列元素:从队头到队尾
int TraverseLinkQueue(LinkQueue *LQ)
{
	LinkListPtr traversePtr = NULL;

	if (LQ->front == LQ->rear)
	{
		printf("空队列!\n");
		return -1;
	}
	traversePtr = LQ->front->next; //指向头结点的下一个结点

	while (traversePtr)
	{
		printf("%d\t ", traversePtr->data);
		traversePtr = traversePtr->next;
	}
	printf("\n");

	return 0;
}

// test demo
int main(int argc, char * argv[])
{
	int ele = 0;
	LinkQueue LQ;
	// 1. 队列初始化
	InitLinkQueue(&LQ);

	// 2.入队列
	EnterLinkQueue(&LQ, 1);
	TraverseLinkQueue(&LQ);

	EnterLinkQueue(&LQ, 2);
	TraverseLinkQueue(&LQ);

	EnterLinkQueue(&LQ, 3);
	TraverseLinkQueue(&LQ);

	// 3.出队列
	DeleteLinkQueue(&LQ, &ele);
	printf("出队元素: %d \n", ele);
	TraverseLinkQueue(&LQ);

	DeleteLinkQueue(&LQ, &ele);
	printf("出队元素: %d \n", ele);
	TraverseLinkQueue(&LQ);

	DeleteLinkQueue(&LQ, &ele);
	printf("出队元素: %d \n", ele);
	TraverseLinkQueue(&LQ);

	return 0;
}

THE END!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞翔的鲲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值