顺序循环队列与链队列

我们一般所说的顺序队列其实就已经是循环顺序队列了,最基础的单向队列有着太多的缺点。

队列的特点是先进先出,就像日常生活的排队一样,先去排队吃饭的人,先打到饭(单通道的情况下)。

1.顺序队列

1.1头文件

在确定了队列需要实现的功能之后,我们就可以编写头文件了,头文件中一般定义了结构体,宏定义,宏替换,例如本文中的N与data_t,N定义了队列的长度,可以只修改头文件中的内容,就可以修改每次用到的数值,data_t 则定义了队列的数据类型,当我们要储存不同的数据类型时,方便修改。

/*===============================================
*   文件名称:sequeue.h
*   创 建 者:     
*   创建日期:2022年07月30日
*   描    述:
================================================*/
#ifndef __SEQUEUE__
#define __SEQUEUE__

#define N 64
typedef int data_t;
typedef struct sequeue
{
	data_t buf[N];
	int front;//头指针
	int rear;//尾指针

}SeQueue;
SeQueue *Create_Sequeue();//创建循环队列

int Sequeue_Is_Full(SeQueue *s);//判满

int Sequeue_Is_Empty(SeQueue *s);//判空

void Enqueue(SeQueue *s,data_t data);//入队

void Dequeue(SeQueue *s,data_t *data);//出队

#endif

1.2功能函数

顺序队列的一大特点是判空与判满的条件,我们在结构体中定义了front与rear两个指针表示数组的下标,也就具备了头尾指针的作用,我们通过头尾指针的指向,来判断队列的情况

空队列:front==rear

满队列: (rear+1)%N==front

在创建队列时,front与rear都指向0,入队的话尾指针+1,出队的话头指针+1

/*===============================================
*   文件名称:sequeue.c
*   创 建 者:     
*   创建日期:2022年07月30日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sequeue.h"

SeQueue *Create_Sequeue()//创建循环队列
{
	SeQueue *s=(SeQueue *)malloc(sizeof(SeQueue));
	if(NULL==s)
	{
		printf("malloc error");
		return NULL;
	}
	memset(s->buf,0,sizeof(s->buf));
	s->front=0;
	s->rear=0;
	return s;
}

int Sequeue_Is_Full(SeQueue *s)//判满
{
	if(s->front==(s->rear+1)%N)
		return 1;
	else
		return 0;
}

int Sequeue_Is_Empty(SeQueue *s)//判空
{
	if(s->front==s->rear)	
		return 1;
	else
		return 0;
}

void Enqueue(SeQueue *s,data_t data)//入队
{
	if(Sequeue_Is_Full(s))
	{
		printf("队列已满,不能插入\n");
		return;
	}	
	s->buf[s->rear]=data;	
	s->rear=(s->rear+1)%N;
	
}

void Dequeue(SeQueue *s,data_t *data)//出队
{
	if(Sequeue_Is_Empty(s))
	{
		printf("队列已空,不能删除\n");
		return;
	}
	*data=s->buf[s->front];
	s->front=(s->front+1)%N;
}

1.3主函数

主函数调用功能函数,创建了一个队列,然后入队10次,出队10次。出队是利用值传递来实现的。

/*===============================================
*   文件名称:main.c
*   创 建 者:     
*   创建日期:2022年07月30日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "sequeue.h"

int main(int argc, char *argv[])
{ 
	int i=0; 
	data_t data;
	SeQueue *s=Create_Sequeue();//创建循环队列

	for(i=0;i<10;i++)
	{	
		Enqueue(s,i);//入队
		printf("%2d",i);
	}
	puts("");
	for(i=0;i<10;i++)
	{
		Dequeue(s,&data);//出队
		printf("%2d",data);
	}
	puts("");
    return 0;
} 

运行结果

 

2.链式队列

2.1头文件

链式队列,我们定义了两种结构体,一种用来保存数据,称为Node节点,一种用来保存队头队尾,称为LinkSqueue,Node有多个,而LinkSequeue,只有一个

/*===============================================
*   文件名称:linkqueue.h
*   创 建 者:     
*   创建日期:2022年07月30日
*   描    述:
================================================*/
#ifndef __LINKQUEUE__
#define __LINKQUEUE__
typedef int data_t;

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

typedef struct linkqueue
{
	struct node *front;
	struct node *rear;
}LinkQueue;


LinkQueue *Creat_Linkqueue();//创建链式队列

int Linkqueue_Is_Empty(LinkQueue *q);//判空

void Enlinkqueue(LinkQueue *q,data_t data);//入队

void Delinkqueue(LinkQueue *q,data_t *data);//出队


#endif

2.2功能函数

功能函数中创建节点很关键,首先创建一个Node类型的头结点,用于保存后面的链表,创建一个LinkSequq节点,把内部的rear和front指向头结点。

插入函数:采用尾插法,rear指向最后一个节点,每次都创建一个新的Node节点,把数据存入Node的数据域data,然后把Node连接到rear与NULL之间,再把rear向后偏移一个,保持rear指向最后一个Node节点,保证每次插入都是最后一个。

删除函数:每次删除front节点的后一个节点。先用m把front的后一个节点的地址保存下来,再执行删除操作,删除之前可以先把m的数据域通过形参data返回,删除之后要判断队列是否为空了,如果此时队列为空(只有头结点了),则把front的地址赋给rear。

/*===============================================
*   文件名称:linkqueue.c
*   创 建 者:     
*   创建日期:2022年07月30日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"


LinkQueue *Creat_Linkqueue()//创建链式队列
{	
	//创建头结点
	Node *head=(Node *)malloc(sizeof(Node));
	if(NULL==head)
	{
		printf("node malloc error");
		return NULL;
	}
	head->data=-1;
	head->next=NULL;
	
	//给链式队列指定头尾指针的指向
	LinkQueue *q=(LinkQueue *)malloc(sizeof(LinkQueue));
	if(NULL==q)
	{
		printf("linkqueue malloc error");
		return NULL;
	}
	//(q->front)->next=head;//不要忘了next?
	//(q->rear)->next=head;
	q->front=head;
	q->rear=head;
	return q;
}

int Linkqueue_Is_Empty(LinkQueue *q)//判空
{
	if(q->front==q->rear)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

void Enlinkqueue(LinkQueue *q,data_t data)//入队,在队尾插入
{
	Node *s=(Node *)malloc(sizeof(Node));
	if(NULL==s)
	{
		printf("node malloc error");
		return ;
	}
	s->data=data;
	s->next=q->rear->next;//s指向空
	q->rear->next=s;	//rear指向s
	q->rear=q->rear->next;	//rear指向最后一个节点
}
void Delinkqueue(LinkQueue *q,data_t *data)//出队,在队头删除,删除之后要判断,是否为空,空了要把rear指向front
{
	if(Linkqueue_Is_Empty(q))//判空
	{
		printf("队列为空,不能删除");
		return;
	}
	Node *m=q->front->next;//先保存要删除的第一个节点的地址
	*data=m->data;		//把出队的元素值返回给data
	q->front->next=m->next;//删除m
	free(m);
	m=NULL;
	if(q->front->next==NULL)//删除后队列为空了
	{
		q->rear=q->front;
	}

}

2.3主函数

主函数简单的测试了功能函数是否能完成任务,输入了10个数,然后出队时,每次出一个,打印一次

/*===============================================
*   文件名称:main.c
*   创 建 者:     
*   创建日期:2022年07月30日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"

int main(int argc, char *argv[])
{ 

	int i=0;
	data_t data;
	LinkQueue *q=Creat_Linkqueue();//创建链式队列

	for(i=0;i<10;i++)
	{
		Enlinkqueue(q,i);//入队
	}
	while(q->front!=q->rear)
	{
		Delinkqueue(q,&data);//出队
		printf("%d",data);
	}
	puts("");
    return 0;
} 

运行结果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值