链式队列的实现

链式队列的概念


1.1 链式队列的定义

  • 链式队列是基于单链表(带头结点)的存储表示实现的队列。


1.2 链式队列中各元素的逻辑及存储关系

  • 链式队列可以采用单链表作为其存储表示,因此,可以在链式队列的声明中用单链表定义它的存储空间。
  • 链式队列的队头指针指向单链表的第一个结点,队尾指针指向单链表的最后一个结点。
  • 注:链式队列的队头元素存放在单链表的第一个结点内,若要从队列中退出一个元素,必须从单链表中删去第一个结点,而存放着新元素的结点应插在队列的队尾,即单链表的最后一个结点后面,这个新节点将成为新的队尾。

1.3 链式队列的特点

  • 用单链表表示的链式队列特别适合于数据元素变动比较大的情况,而且不存在队列满而产生溢出的情况。
  • 若程序中要使用多个队列,用链接表示不仅能够提高效率,还可以达到共享存储空间的目的。
  • 使用链式队列不会出现存储分配不合理的问题,也不需要进行存储的移动。

链式队列的图示

C++语言实现

/*链式队列(Linked Queue)相关操作*/
 
#include <iostream>
#include <malloc.h>
#include <cstdlib>

using namespace std;

//链式队列结点
typedef struct QNode{
	char data;   //元素值 
	struct QNode *next;    //指向下一个结点的指针 
}QNode, *QueuePtr;

//链式队列结构
typedef struct{
	QueuePtr front;  //队头指针
	QueuePtr rear;   //队尾指针 
}LinkQueue; 

//初始化队列
bool InitQueue(LinkQueue *Q) 
{
	Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));  //为队头指针和队尾指针分配所指向的内存(即为空表头分配内存) 
	if(!Q->front || !Q->rear)  //内存分配失败 
		exit(0);
	Q->front->next = NULL;  //空表头指向NULL
	return true; 
}

//销毁队列
bool DestroyQueue(LinkQueue *Q)
{
	while(Q->front != NULL)  //从空表头开始沿着链表的顺序依次释放结点 
	{
		Q->rear = Q->front->next;
		free(Q->front);  //释放队头指针所指结点
		Q->front = Q->rear;
	}
	return true;
} 

//清空队列
bool ClearQueue(LinkQueue *Q)
{
	QueuePtr p, q;
	p = Q->front->next;
	Q->front->next = NULL;
	Q->rear = Q->front;
	while(p != NULL)
	{
		q = p;   //q指向被释放结点 
		p = p->next;
		free(q);
	}
	return true;
} 

//判断队列是否为空
bool QueueEmpty(LinkQueue Q)
{
	if(Q.front == Q.rear)
		return true;
	else
		return false;
} 

//获取队列长度
int QueueLength(LinkQueue Q)
{
	int length = 0;
	QueuePtr p = Q.front;  //p用于遍历整个队列 
	while(p != Q.rear)
	{
		length++;
		p = p->next;
	}
	return length;
} 

//获取队列头元素(队列第一个元素)
bool GetHead(LinkQueue Q, char *elem)
{
	if(Q.front == Q.rear)  //队列为空
	{
		cout<<"队列为空,获取队头元素失败!"<<endl; 
		return false;
	} 
	*elem = Q.front->next->data;
	return true;
} 

//入队
bool EnQueue(LinkQueue *Q, char elem) 
{
	QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
	if(!p)   //内存分配失败 
		exit(0);
	p->data = elem;
	p->next = NULL;
	Q->rear->next = p;
	Q->rear = p;
	return true; 
}

//出队
bool DeQueue(LinkQueue *Q, char *elem)
{
	if(Q->front == Q->rear)  //队列为空
	{
		cout<<"队列为空!"<<endl; 
		return false;
	} 
	QueuePtr q;
	q = Q->front->next;  //q指向队列的第一个元素 
	*elem = q->data; 
	Q->front->next = q->next; 
	if(q == Q->rear)  //队列只有一个元素(即被删除结点是队尾指针指向的结点,删除后队列为空)
	{
		Q->rear = Q->front;
	}
	free(q);
	return true;
} 

//遍历队列
bool TravelQueue(LinkQueue Q)
{
	QueuePtr p;
	p = Q.front->next;
	while(p)
	{
		cout<<p->data<<" ";
		p = p->next;
	}
	cout<<endl;
	return true;
}

int main()
{   
	char temp;
    char e;       //元素值
    LinkQueue Q;  //队列

    /*** 初始化队列 ***/
    InitQueue(&Q); 
    cout<<"初始化队列后,队列是否为空? ";
	if(QueueEmpty(Q))
		cout<<"是"<<endl;
	else
		cout<<"否"<<endl;
	
    /*** 向队列中插入元素 ***/
    cout<<"向队列中插入元素:"<<endl;
    while(cin>>temp)
	{
    	EnQueue(&Q, temp);  //将元素temp插入队列
    	if(cin.get() == '\n')
			break;
    }
    cout<<"插入元素后队列的值为:"<<endl;
    TravelQueue(Q);   //遍历队列
    
    cout<<"队列的长度为:"<<QueueLength(Q)<<endl;   //获取队列长度
    
    cout<<"插入元素后,队列是否为空? ";
    if(QueueEmpty(Q))
		cout<<"是"<<endl;
	else
		cout<<"否"<<endl;

    /*** 删除队列中的3个元素,并打印对应的值 ***/
    cout<<"出队3个元素,依次为:";
    for (int j=0; j<3; j++) 
	{
        DeQueue(&Q, &e); // 删除队头元素,将值存到e中
        cout<<e<<" ";
    }
    cout<<endl;
    
    cout<<"3个元素出队后,队列的值为:"<<endl;
    TravelQueue(Q);    //遍历队列
    
    cout<<"队列的长度为:"<<QueueLength(Q)<<endl;    //获取队列长度

    /*** 获取队列头元素的值 ***/  
    if(GetHead(Q, &e))     //获取队列头元素
	{
        cout<<"队列头元素为:"<<e<<endl;
    }

    /*** 清空队列元素 ***/
    ClearQueue(&Q);       //清空队列元素
    
    cout<<"清空队列后,队列是否为空? ";
    if(QueueEmpty(Q))
		cout<<"是"<<endl;
	else
		cout<<"否"<<endl;
		
    cout<<"队列中的元素为:"<<endl;
    TravelQueue(Q); // 遍历元素
    
    if(DestroyQueue(&Q)) 
    	cout<<"已销毁队列!"<<endl;
    
	return 0; 
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值