关于队列的学习

队列,是一种操作被限制的线性表,分为顺序队列(循环)和链式队列


一、循环顺序队列

1、基本概念

存储就是数组,一个队列头指针(数组的下标),一个队列尾指针(数组的下标),入队只能从数组尾入(下标大的),出队只能从数组头出(下标小的),可以循环存放。

队列遵循先入先出,后入后出的规则

2、名词解释

 MAXSIZE:数组的最大存放值

 front:头指针

 rear:尾指针

3、队列的判定与计算通式

1、队空:front=rear

2、队满:front==(rear+1)%MAXSIZE

3、队长度:(rear-front+MAXSIZE)%MAXSIZE

      实则是两部分组成:1.当rear<front时      ((MAXSIZE-front)+rear)%MAXSIZE

                                  2.当rear>front         (rear-front)% MAXSIZE

4、循环移动:rear=(rear+1)%MAXSIZE

                    front=(front+1)%MAXSIZE

4、头尾指针的位置

因为队空判断和队满判断的原因,所以一般规定头指针front指向的数组元无数据,尾指针rear指向的数组元有数据,初始化时使得头尾指针都为-1.

 5、循环队列的操作

(1)队列结构的定义

typedef struct stu//队列的结构定义
{
	int a[MAXSIZE];//队列存储的空间
	int front,rear;//数组的下标,循环队列的头尾指针
}squ;

(2)队列结构的初始化

squ* Initqueue()//队列结构初始化
{
	squ* st=(squ*)malloc(sizeof(squ));
	st->front=-1;//头尾都为0,此时是空对
	st->rear=-1;//
	return st;
}

(3)入队

void pushSqueue(squ* st1,int n)//入队,在尾,n是入队的数据
{
	
	if(st1->front==(((st1->rear)+1)%MAXSIZE))
	{
		printf("!!!!入队失败\n");
		return;//判断满队不能入队
	}
	st1->rear=(st1->rear+1)%MAXSIZE;//移动尾指针
	st1->a[st1->rear]=n;//将数据放入尾指针的地址
}

(4)出队

int popSqueue(squ* st)//出队,在头,返回的是出队的数据
{
	int n;
	if(st->front==st->rear)return 0;//判断是否队空
	st->front=(st->front+1)%MAXSIZE;//移动头指针
	n=st->a[st->front];//将头指针的数据出给n
	return n;
}

(5)清队

void claerqueue(squ* st)//清除队列
{
	if(st->front==st->rear)return;//判断队列是否为空
	st->front=-1;//不为空置为空队列
	st->rear=-1;//
	return;
}

(6)展示队

void showqueue(squ* st)//展示队列内容
{
	int i=0;//头尾指针都不能随意移动,所以用个i代替移动
	printf("队列的展示:\n");
	for(i=((st->front)+1);i<=(st->rear);i=(i+1)%MAXSIZE)//
	{
		printf("%d ",st->a[i]);
	}
	putchar('\n');
	printf("队列的长度为:%d\n",((st->rear)-(st->front)+MAXSIZE)%MAXSIZE);
}

6、总程序

//队空:front=rear
//队满:front==(rear+1)%MAXSIZE
//队长度:(rear-front+MAXSIZE)%MAXSIZE
//循环移动:rear=(rear+1)%MAXSIZE
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
typedef struct stu//队列的结构定义
{
	int a[MAXSIZE];//队列存储的空间
	int front,rear;//数组的下标,循环队列的头尾指针
}squ;
squ* Initqueue()//队列结构初始化
{
	squ* st=(squ*)malloc(sizeof(squ));
	st->front=-1;//头尾都为0,此时是空对
	st->rear=-1;//
	return st;
}
void pushSqueue(squ* st1,int n)//入队,在尾,n是入队的数据
{
	
	if(st1->front==(((st1->rear)+1)%MAXSIZE))
	{
		printf("!!!!入队失败\n");
		return;//判断满队不能入队
	}
	st1->rear=(st1->rear+1)%MAXSIZE;//移动尾指针
	st1->a[st1->rear]=n;//将数据放入尾指针的地址
}
int popSqueue(squ* st)//出队,在头,返回的是出队的数据
{
	int n;
	if(st->front==st->rear)return 0;//判断是否队空
	st->front=(st->front+1)%MAXSIZE;//移动头指针
	n=st->a[st->front];//将头指针的数据出给n
	return n;
}
void claerqueue(squ* st)//清除队列
{
	if(st->front==st->rear)return;//判断队列是否为空
	st->front=-1;//不为空置为空队列
	st->rear=-1;//
	return;
}
void showqueue(squ* st)//展示队列内容
{
	int i=0;//头尾指针都不能随意移动,所以用个i代替移动
	printf("队列的展示:\n");
	for(i=((st->front)+1);i<=(st->rear);i=(i+1)%MAXSIZE)//
	{
		printf("%d ",st->a[i]);
	}
	putchar('\n');
	printf("队列的长度为:%d\n",((st->rear)-(st->front)+MAXSIZE)%MAXSIZE);
}
void main()
{
	squ* st;
	int n;
	st=Initqueue();//队列结构初始化
	pushSqueue(st,10);//入队,在尾,n是入队的数据
	pushSqueue(st,20);
	pushSqueue(st,30);
	pushSqueue(st,40);
	n=popSqueue(st);//出队,在头,返回的是出队的数据
	printf("出队的数据为:%d\n",n);
	//claerqueue(st);//清除队列
	showqueue(st);//展示队列内容
}

二、队链

实则就是链表的操作限制,从头出队,尾插法入队,所以用到两个指针,一个指向头head,一个指向尾rear

1、节点结构和队结构

typedef struct lnode//节点结构
{
	int data;//节点的数据域
	struct lnode* next;//节点的指针域
}Listnode;
typedef struct//队结构
{
	int num;//计数
	Listnode *head,*rear;//头尾指针
}prequeue;

2、队的初始化

prequeue* Init()//维护的初始化,返回维护结构的地址
{
	prequeue* st=(prequeue*)malloc(sizeof(prequeue));//申请队结构的内存空间
	st->num=0;//初始化将队列的计数为0
	st->head=st->rear=NULL;//头尾指针指向NULL
	return st;//返回队结构的地址
}

3、入队(链队没有内存的限制)

void pushqueue(prequeue* st,int n)//入队(队结构的地址,入队的数据)
{
	Listnode* tmp;//新节点的地址
	if(!st)return;
	tmp=(Listnode*)malloc(sizeof(Listnode));//申请新新节点的空间
	tmp->data=n;//节点的初始化
	tmp->next=NULL;
	if((st->num)==0)//如果是第一次入队列
	{
		st->rear=st->head=tmp;//头指针指向新节点
		(st->num)++;
		return;
	}
	else
	{
		st->rear->next=tmp;//将尾节点的指针域指向新节点tmp
		st->rear=st->rear->next;//移动尾指针指向新入队的节点
		(st->num)++;
		return;
	}
}

4、出队

int popqueue(prequeue* st)//出队,返回出队的数据
{
	int n;
	Listnode *p=NULL;
	if(!st || !(st->num))return 0;
	p=st->head;//从队头出
	n=p->data;
	st->head=st->head->next;//移动头指针到下一个节点
	free(p);
	p=NULL;
	(st->num)--;
	return n;//
}

5、队遍历

void readqueue(prequeue* st)//遍历输出队列
{
	Listnode* p;
	if(!st || !(st->num))return;
	p=st->head;//从队头开始
	while(p!=NULL)//p不指向空
	{
		printf("%d ",p->data);
		p=p->next;//移动p
	}
	putchar('\n');
}

6、清除队

void clearqueue(prequeue *st)//清空队列
{
	Listnode *p;
	if(!st || st->num==0)return;
	while(!(st->head==NULL))//头指针不为NULL时代表队列不为空
	{
		p=st->head;//从头开始
		st->head=st->head->next;//头指针移动到下一个节点
		free(p);//释放上一个节点
		p=NULL;
		(st->num)--;
	}
}

7、总程序

#include <stdio.h>
#include <stdlib.h>
typedef struct lnode//节点结构
{
	int data;//节点的数据域
	struct lnode* next;//节点的指针域
}Listnode;

typedef struct//队结构
{
	int num;//计数
	Listnode *head,*rear;//头尾指针
}prequeue;

prequeue* Init()//维护的初始化,返回维护结构的地址
{
	prequeue* st=(prequeue*)malloc(sizeof(prequeue));//申请队结构的内存空间
	st->num=0;//初始化将队列的计数为0
	st->head=st->rear=NULL;//头尾指针指向NULL
	return st;//返回队结构的地址
}

void pushqueue(prequeue* st,int n)//入队(队结构的地址,入队的数据)
{
	Listnode* tmp;//新节点的地址
	if(!st)return;
	tmp=(Listnode*)malloc(sizeof(Listnode));//申请新新节点的空间
	tmp->data=n;//节点的初始化
	tmp->next=NULL;
	if((st->num)==0)//如果是第一次入队列
	{
		st->rear=st->head=tmp;//头指针指向新节点
		(st->num)++;
		return;
	}
	else
	{
		st->rear->next=tmp;//将尾节点的指针域指向新节点tmp
		st->rear=st->rear->next;//移动尾指针指向新入队的节点
		(st->num)++;
		return;
	}
}

int popqueue(prequeue* st)//出队,返回出队的数据
{
	int n;
	Listnode *p=NULL;
	if(!st || !(st->num))return 0;
	p=st->head;//从队头出
	n=p->data;
	st->head=st->head->next;//移动头指针到下一个节点
	free(p);
	p=NULL;
	(st->num)--;
	return n;//
}

void readqueue(prequeue* st)//遍历输出队列
{
	Listnode* p;
	if(!st || !(st->num))return;
	p=st->head;//从队头开始
	while(p!=NULL)//p不指向空
	{
		printf("%d ",p->data);
		p=p->next;//移动p
	}
	putchar('\n');
}

void clearqueue(prequeue *st)//清空队列
{
	Listnode *p;
	if(!st || st->num==0)return;
	while(!(st->head==NULL))//头指针不为NULL时代表队列不为空
	{
		p=st->head;//从头开始
		st->head=st->head->next;//头指针移动到下一个节点
		free(p);//释放上一个节点
		p=NULL;
		(st->num)--;
	}
}




void main()
{
	//int ndata;//
	prequeue *st;//定义队结构
	st=Init();//初始化
	pushqueue(st,10);//入队
	pushqueue(st,20);
	pushqueue(st,30);
	pushqueue(st,40);
	pushqueue(st,50);
	//ndata=popqueue(st);//出队
	readqueue(st);//遍历队
	//printf("出队的数据%d ,队长度为%d \n",ndata,st->num);
	clearqueue(st);//清除队
	printf("执行清除后的剩余的队列长度为%d\n",st->num);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值