数据结构——链式队列【c语言版】

  队列(quque)简称队,只允许在表的一端输入,在表的另一端删除(操作受限制的线性表),

把进行插入的一段叫做队尾(表尾),把进入删除的一端叫做队首或队头(表头)。

队列最主要的特点:先进先出,FIFO(first in first out)

队列有其实有三种:顺序队列、 循环队列、链式队列

      采用链式存储结构实现的队列称为链队

        下面是采用单链表来实现链式队列的过程:

        在链队中只允许单链表的表头进行删除操作(出队),表尾进行插入操作(入队),因此需要使用两个指针(一个是对头指针front【指向队首结点】,另一个是队尾指针rear【指向队尾结点】)。 

链队数据结点类型DataNode如下:

typedef int ElemType;

//值节点--多个 
typedef struct Node
{
	ElemType data;//存储队列的元素值 
	struct Node *next;//存储下一个元素节点的地址 
}DataNode;

链队存储结构如图:

链队头结点类型LinkQueue如下:

//头节点--1个 
typedef struct
{
	DataNode *front;//存储队头元素节点的地址 (队首指针) 
	DataNode *rear;//存储队尾元素节点的地址 (队尾指针)
}LinkQueue;

链队的动态变化过程如图:

对于链式队列来说,有以下四个非常重要的要素:

        1.队空条件:q->front==NULL && q->rear==NULL 

        2.队满条件:与链栈一样,链队一般不会满,不存在队满上溢情况 

        3.进队操作:新建一个结点存放元素e,将结点t插入作为尾结点

        4.出队操作:构造一个结点t,让t指向队首元素节点,把队首元素存储到*e中,删除队头元                                   素节点

1)链队初始化

        构造一个空的队列,既创建一个链队结点,将front和rear域都设置为NULL,代码如下:

LinkQueue *InitQueue()
{
	LinkQueue *q;
	q=(LinkQueue *)malloc(sizeof(LinkQueue));
	q->front=NULL;
	q->rear=NULL;
	return q;
} 

2)销毁队列

        释放队列占用的全部存储空间,包括链队结点与所以数据结点的存储空间,代码如下:

void DestroyQueue(LinkQueue *q)
{
	int deQueue(LinkQueue *q,ElemType *e);
	ElemType m;
	
	while(q->front!=NULL||q->rear!=NULL)//非空
	{
		//出队
		deQueue(q,&m); 
	} 
	free(q);
} 

3)判断队列是否为空

        链式队列中,判断队列是否为空,只需要判断q->front==NULL && q->rear==NULL的条件成立即可,代码如下:

//判断队列为空

int QueueEmpty(LinkQueue *q)
{
	if(q->front==NULL && q->rear==NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
} 

4)入队

       构造一个节点t,data域存储e,next域存储NULL,若原链队为空,则将链队结点的两个域都指向结点t,否则将结点t链接到单链表末尾,并让链队结点的rear域指向它,代码如下:

void enQueue(LinkQueue *q,ElemType e)
{
	DataNode *t;
	//1.构造一个节点t,data域存储e,next域存储NULL
	t=(DataNode *)malloc(sizeof(DataNode));
	t->data=e;
	t->next=NULL;
	//2.添加 
	if(q->front!=NULL||q->rear!=NULL)//非空
	{
		/*队非空*/
		q->rear->next=t;
		q->rear=t;
	} 
	else
	{
		/*队空 */
		q->front=t;
		q->rear=t;
	} 	
} 

5)出队

         若原链队为空,则下溢,提示,返回0,否则将队首结点的data域赋值给*e,并删除队首结点,若原链队只有一个结点,则需要将链队结点的两个域都设置为NULL,表示此时链队已空,代码如下:

/* 
若队列非空,出队,返回1;
否则,提示,返回0 
*/
int deQueue(LinkQueue *q,ElemType *e)
{
	DataNode *t;
	
	if(q->front!=NULL||q->rear!=NULL)//非空
	{
		//1.让t指向队头元素节点
		t=q->front;
		//2.把队头元素存储到*e中
		*e=t->data;
		//3.删除队头元素节点
		if(q->front->next==NULL)//只有1个元素
		{
			/*只有1个元素*/
			q->front=NULL;
			q->rear=NULL;
		} 
		else
		{
			/*多于1个元素*/
			q->front=t->next;
		}	
		//4.释放t所占的存储空间
		free(t); 
		return 1;
	} 
	else
	{
		printf("队空,不能出队!\n");
		return 0;
	}	
} 

6)求队列长度

代码如下:

/*
6.求链式队列的长度 
*/
int lenghtLinkQueue(LinkQueue *q)
{
	int len;
	if (QueueEmpty(&q))
 	{
  		len = 0;
	 	return len;
	}
	DataNode *t;
	//1.构造一个节点t,让它指向队首元素front 
	t=(DataNode *)malloc(sizeof(DataNode));
	t=q->front;
	len = 1;
	while(t->next != NULL)
	{
		len++;
		t = t->next;
	}
	printf("队列长度为%d\n",len);	

} 

7)打印队列中的元素

        从队首到队尾,代码如下:

//打印队列中的与元素
void DispQueue(LinkQueue *q)
{
	DataNode *p; 
	p=q->front;
	printf("队列元素为:");
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}

下面是入队、出栈和打印出队列以及销毁队列元素的操作:

int main()
{
	LinkQueue lq;
	lq = *InitQueue(); 
	
	enQueue(&lq,1);
	enQueue(&lq,2);
	enQueue(&lq,3);
	enQueue(&lq,4);
	enQueue(&lq,5);
	enQueue(&lq,6);
	enQueue(&lq,7);
	enQueue(&lq,8);
	enQueue(&lq,9);
	DispQueue(&lq);
	lenghtLinkQueue(&lq);
	
	ElemType *e;
	e = (ElemType *)malloc(sizeof(ElemType));
	deQueue(&lq,e);
	printf("出队元素:%d\n",*e);
	deQueue(&lq,e);
	printf("出队元素:%d\n",*e);
	
	 
	printf("队列为空返回1,否则返回0:%d\n",QueueEmpty(&lq));

	DispQueue(&lq);
	lenghtLinkQueue(&lq);
	DestroyQueue(&lq); //销毁队列 
	
	return 1;
} 

测试结构如下

 

最后再附上完整代码:

#include <stdio.h>

typedef int ElemType;

//值节点--多个 
typedef struct Node
{
	ElemType data;//存储队列的元素值 
	struct Node *next;//存储下一个元素节点的地址 
}DataNode;

//头节点--1个 
typedef struct
{
	DataNode *front;//存储队头元素节点的地址 (队首指针) 
	DataNode *rear;//存储队尾元素节点的地址 (队尾指针)
}LinkQueue;

/*
空:q->front==NULL && q->rear==NULL 
满:与链栈一样,链队一般不会满,不存在队满上溢情况 
*/

/*
1.初始化 
*/
LinkQueue *InitQueue()
{
	LinkQueue *q;
	q=(LinkQueue *)malloc(sizeof(LinkQueue));
	q->front=NULL;
	q->rear=NULL;
	return q;
} 

/*
2.销毁 
*/
void DestroyQueue(LinkQueue *q)
{
	int deQueue(LinkQueue *q,ElemType *e);
	ElemType m;
	
	while(q->front!=NULL||q->rear!=NULL)//非空
	{
		//出队
		deQueue(q,&m); 
	} 
	free(q);
} 

/*
3.判断是否为空
若为空,返回1;
否则,返回0 
*/
int QueueEmpty(LinkQueue *q)
{
	if(q->front==NULL && q->rear==NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
} 

/*
4.进队 
*/
void enQueue(LinkQueue *q,ElemType e)
{
	DataNode *t;
	//1.构造一个节点t,data域存储e,next域存储NULL
	t=(DataNode *)malloc(sizeof(DataNode));
	t->data=e;
	t->next=NULL;
	//2.添加 
	if(q->front!=NULL||q->rear!=NULL)//非空
	{
		/*队非空*/
		q->rear->next=t;
		q->rear=t;
	} 
	else
	{
		/*队空 */
		q->front=t;
		q->rear=t;
	} 	
} 

/*
5.出队 
若队列非空,出队,返回1;
否则,提示,返回0 
*/
int deQueue(LinkQueue *q,ElemType *e)
{
	DataNode *t;
	
	if(q->front!=NULL||q->rear!=NULL)//非空
	{
		//1.让t指向队头元素节点
		t=q->front;
		//2.把队头元素存储到*e中
		*e=t->data;  // 其实是q->front->data 
		//3.删除队头元素节点
		if(q->front->next==NULL)//只有1个元素
		{
			/*只有1个元素*/
			q->front=NULL;
			q->rear=NULL;
		} 
		else
		{
			/*多于1个元素*/
			q->front=t->next;
		}	
		//4.释放t所占的存储空间
		free(t); 
		return 1;
	} 
	else
	{
		printf("队空,不能出队!\n");
		return 0;
	}	
} 

/*
6.求链式队列的长度 
*/
int lenghtLinkQueue(LinkQueue *q)
{
	int len;
	if (QueueEmpty(&q))
 	{
  		len = 0;
	 	return len;
	}
	DataNode *t;
	//1.构造一个节点t,让它指向队首元素front 
	t=(DataNode *)malloc(sizeof(DataNode));
	t=q->front;
	len = 1;
	while(t->next != NULL)
	{
		len++;
		t = t->next;
	}
	printf("队列长度为%d\n",len);	

} 
/*
7.输出 
*/
void DispQueue(LinkQueue *q)
{
	DataNode *p; 
	p=q->front;
	printf("队列元素为:");
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}

int main()
{
	LinkQueue lq;
	lq = *InitQueue(); 
	
	enQueue(&lq,1);
	enQueue(&lq,2);
	enQueue(&lq,3);
	enQueue(&lq,4);
	enQueue(&lq,5);
	enQueue(&lq,6);
	enQueue(&lq,7);
	enQueue(&lq,8);
	enQueue(&lq,9);
	DispQueue(&lq);
	lenghtLinkQueue(&lq);
	
	ElemType *e;
	e = (ElemType *)malloc(sizeof(ElemType));
	deQueue(&lq,e);
	printf("出队元素:%d\n",*e);
	deQueue(&lq,e);
	printf("出队元素:%d\n",*e);
	
	 
	printf("队列为空返回1,否则返回0:%d\n",QueueEmpty(&lq));

	DispQueue(&lq);
	lenghtLinkQueue(&lq);
	DestroyQueue(&lq); //销毁队列 
	
	return 1;
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值