循环队列和链式队列的结构及其基本操作(入队、出队、取队头、查看对内元素)

循环队列

队列:只允许在一端进行插入操作,在另一端进行删除操作;数据存储在一个一维数组中
特点:先进先出(FIFO)结构
队头(front):删除数据的一端
队尾(rear):插入数据的一端
顺序队列的缺点:空队时front和rear都指向下标-1处,进队时rear先+1,再放入数据,出队时front先+1,再删数据

队满时一个个删数据,当front和rear都指向最后的位置时,前面的空间空余出来不能再使用。

循环队列的特点:存放数据的数组空间可以反复使用,单需要空出一个空间来区分队头队尾(以下程序中默认front的指向位置不存数据)。

反复使用存储空间的实现操作:front(rear)的操作:front(rear) = (front(rear)+1) % SIZE(存储数据的数组大小)

原因:当front(rear)走到队列最后(数组最大下标=SIZE-1)时,想要返回队列开头(数组最小下标=0)时,利用上述公式   (( SIZE-1)  +1) % SIZE == SIZE % SIZE ==0(数组最小下标)。

队满情况:(rear+1)%SIZE ==front

队列长度:(rear-front+SIZE)% SIZE

队列结构和基本操作函数
#include <stdio.h>
#define ERROR 0
#define OK    1
#define SIZE  11//队列空间大小

typedef struct queue
{
	int data[SIZE];
	int front;//队头,删除
	int rear;//队尾,新增
}Queue;

//创建
int InitQueue(Queue *q)
{
	if(q == NULL)
		return ERROR;
	//初始化
	q->front = 0;
	q->rear  = 0;
	
	return OK;
}

//新增
int Add(Queue *q, int data)
{
	if(q == NULL || q->front == (q->rear + 1)%SIZE)
		return ERROR;
	
	q->rear = (q->rear + 1) % SIZE;//最开始空队列状态时,rear == front == 0;数据进队要先将rear往后移一位再存数据
	q->data[q->rear] = data;
	
	return OK;
}

//删除
int Delete(Queue *q, int *x)
{
	if (q == NULL || q->rear == q->front)
		return ERROR;
	
	q->front = (q->front + 1) % SIZE;//front所在的位置不存(不读取)数据,删除数据就让front指向该数据的位置(队列只能从头开始依次删除数据)
	*x = q->data[q->front];//main函数中的x获取删除的数据
	
	return OK;
}

//取队头数据
int GetFront(Queue *q, int *x)
{
	if (q == NULL)
		return ERROR;
	
	int data = (q->front+1) % SIZE;
	*x = q->data[data];
	
	return OK;
}

//打印数据
void print(Queue q)
{
	if (q.rear == q.front)
	{
		printf("队列为空\n");
		return;
	}

	int begin = (q.front + 1)%SIZE;//队列开头数据的下标,队头标志front所在位置的数据不读取(不存值)
	int beyond = (q.rear + 1)%SIZE;//队列结尾数据的下一个位置的下标
	int i;
	for (i = begin; i != beyond; i = (i+1)%SIZE)//i从队列开头数据下标开始,依次往后加1,到队里最后时需要返回操
	{                                           //作,一直到beyond的前一个位置
		printf("%-4d", q.data[i]);//从队头第一个数据开始一直打印到最后一个数据
	}
	
	printf("\n");
}

//队列长度
int Length(Queue q)
{
	return (q.rear - q.front + SIZE)%SIZE;
}

主函数,举例实践
int main()
{
	Queue q;
	InitQueue(&q);
	
	int i;
	for (i = 1; i < 11; i++)
	{
		Add(&q, i);
	}
	printf("当前队列中数据\n");
	print(q);
	
	int front;
	printf("队头数据:%d\n", GetFront(&q, &front));
	
	int x;
	
	printf("出队数据\n");
	for (i = 1; i < 3; i++)//出队两个
	{
		Delete(&q, &x);
		printf("%-4d", x);
	}
	printf("\n");
	
	//进队两个
	Add(&q, 9);
	Add(&q, 10);
	
	printf("当前队列中数据\n");
	print(q);
	
	return 0;
}

链式队列

链式队列没有队满情况,可以添加任意个结点,操作特点:尾插头删

#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OK    1

typedef struct node
{
	int data;
	struct node *next;
}Node;

typedef struct queue
{
	Node* front;//队头,删除
	Node* rear;//队尾,新增
}Queue;


//创建
Queue* InitQueue()
{
	Queue* q = (Queue*)malloc(sizeof(Queue));
	if (q == NULL)
		return ERROR;
	
	q->front = NULL;
	q->rear  = NULL;
	
	return q;
}

//新增
int Add(Queue *q, int data)
{
	if(q == NULL)
		return ERROR;
	//创建一个新结点
	Node* node = (Node*)malloc(sizeof(Node));
	if (NULL == node)
		return ERROR;
	node->data = data;
	node->next = NULL;//尾插
	
	if (q->front == NULL)//队列为空情况,队头队尾指针都指向新结点
	{
		q->front = node;
		q->rear  = node;
	}
	else//队列不空
	{
		q->rear->next = node;//队尾结点指向新结点
		q->rear = node;//队尾指针指向队尾(新建结点插在队尾)
	}
	return OK;
}

//删除
int Delete(Queue *q, int *x)
{
	if (q == NULL || q->front == NULL)
		return ERROR;
	
	Node* p = q->front;//保存当前队列的第一个结点地址
	*x = p->data;
	
	q->front = p->next;//队头指针指向原先队列的第二个结点(原先第二结点充当新队列的第一结点)
	free(p);//释放(删除)原先第一结点的空间
	
	if (q->front == NULL)//如果删除一个结点后,队列为空
		q->rear == NULL;//原先队列只有一个结点的情况下,rear指向被删结点的空间,删除结点后需要置空
	
	return OK;
}

//打印数据
void print(Queue *q)
{
	if (NULL == q->front)
	{
		printf("队列为空\n");
		return;
	}

	Node* tmp = q->front;//tmp指向队列第一个结点
	while (tmp)
	{
		printf("%-4d", tmp->data);
		tmp = tmp->next;
	}
	
	printf("\n");
}


int main()
{
	Queue* q = InitQueue();
	
	int i;
	for (i = 1; i < 11; i++)
	{
		Add(q, i);
	}
	printf("当前队列中数据\n");
	print(q);
	
	
	int x;
	
	printf("出队数据\n");
	for (i = 1; i < 11; i++)//出队
	{
		Delete(q, &x);
		printf("%-4d", x);
	}
	printf("\n");
	
	
	
	printf("当前队列中数据\n");
	print(q);
	
	return 0;
}




  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值