数据结构—队列的链式表示和实现

链队是指采用链式存储结构实现的队列。通常链队用单链表来表示,如图所示。一个链队显然需要两个分别指示队头和队尾的指
针(分别称为头指针和尾指针)才能唯一确定。这里和线性表的单链表一样,为了操作方便起见,给链队添加一个头结点,并令头指针始终指向头结点。

1.队列的链式表示

typedef struct QNode 
{
	int data;
	struct QNode *next;
}QNode, *QueuePtr;

typedef struct 
{
	QueuePtr front;  // 队头指针
	QueuePtr rear;   // 队尾指针
}LinkQueue;

2.链队的初始化

  • 链队的初始化操作就是构造一个只有一个头结点的空队,如图(a)所示
  • 算法步骤
    • ①生成新结点作为头结点,队头和队尾指针指向此结点。
    • ②头结点的指针域置空。
  • 算法描述
int InitQueue(LinkQueue &Q) 
{
	//构造一个空队列 
	Q.front = Q.rear = new QNode;  // 生成新结点作为头结点,队头和队尾指针指向此结点
	if (!Q.front) 
	{
		return 0;   // 没有生成头结点,初始化失败. 
	}
	Q.front->next = NULL;   // 头结点指针域置空
	return 1;
}

2.入队

  • 和循环队列的入队操作不同的是,链队在入队前不需要判断队是否满,需要为入队元素动态分配一个结点空间,如图(b)和(c)所示。
  • 算法步骤
    • ①为入队元素分配结点空间,用指针p指向。
    • ②将新结点数据域置为e。
    • ③将新结点插入到队尾
    • ④修改队尾指针为p
  • 算法描述
int EnQueue(LinkQueue &Q, int e) 
{
	//插入e为Q的新的队尾元素
	QNode *s;
	s = new QNode;
	if (!s) 
	{
		return 0;  //存储分配失败 
	}
	s->data = e;
	s->next = NULL;
	Q.rear->next = s;  // 将新节点插入到队尾
	Q.rear = s;     //修改尾指针 
	return 1;
}

3.出队

  • 和循环队列一样,链队在出队前也需要判断队列是否为空,不同的是,链队在出队后需要释放出队头元素的所占空间,如图(d)所示。
  • 算法步骤
    • ①判断队列是否为空,若空则返回 ERROR。
    • ②临时保存队头元素的空间,以备释放。
    • ③修改队头指针,指向下一个结点。
    • ④判断出队元素是否为最后一个元素,若是,则将队尾指针重新赋值,指向头结点。
    • ⑤释放原队头元素的空间。
int DeQueue(LinkQueue &Q, int &e) 
{
	QNode *p;
	if (Q.front == Q.rear) 
	{
		return 0;//队列为空 
	}
	p = Q.front->next;   // 指针p指向队列的第一个元素
	e = p->data;
	Q.front->next = p->next;   // 修改头结点的指针域
	if (Q.rear == p) 
	{
		Q.rear = Q.front;
	}   // 最后一个元素被删除,队尾指针指向头结点
	delete p;  // 释放原队头元素所占的空间
	return 1;
}

5.取队头元素

  • 与循环队列一样,当队列非空时,此操作返回当前队头元素的值,队头指针保持不变。
  • 算法描述
int GetHead(LinkQueue Q)
{
	// 返回Q的队头元素, 不修改队头指针
	if (Q.front != Q.rear)   //队列非空
		return Q.front->next->data;  // 返回队头元素的值,队头指针不变
}

6.代码实现

  • main.cpp
#include <iostream>

#define MAXQSIZE 100

using namespace std;

// 定义顺序队列
typedef struct 
{
	int *base;   //分配存储空间 
	int front;  //队头指针 
	int rear;  //队尾指针 
}SqQueue;


//初始化循环队列 
int InitQueue(SqQueue &Q) 
{
	Q.base = new int[MAXQSIZE];   //分配存储空间
	if (!Q.base) 
		return 0;     // 存储空间分配失败 
	Q.front = Q.rear = 0;
	
	return 1;
}

// 求队列的长度
int QueueLength(SqQueue Q)
{
	return ((Q.rear - Q.front) + MAXQSIZE) % MAXQSIZE;
}


// 入队操作
int EnQueue(SqQueue &Q, int e) 
{
	//首先判断队列是否已满
	if ((Q.rear + 1) % MAXQSIZE == Q.front) 
	{
		return 0;
	}
	Q.base[Q.rear] = e;  // 新元素插入队尾
	Q.rear = (Q.rear + 1) % MAXQSIZE;   // 队尾指针加1
	return 1;
}

//出队操作
 int DeQueue(SqQueue &Q, int &e) 
 {
	if (Q.front == Q.rear)
	{
		return 0;
	}
	e = Q.base[Q.front];  // 保存队头元素
	Q.front = (Q.front + 1) % MAXQSIZE;  // 队头指针加1
	
	return 1;
}

// 取队头元素
int GetHead(SqQueue Q)// 返回Q的队头元素, 不修改队头指针
 {
	 if (Q.front != Q.rear)   // 队列非空
		 return Q.base[Q.front];  // 返回队头元素的值,队头指针不变
 }
	 
//遍历队列
void TraveQueue(SqQueue Q) 
{
	int len = QueueLength(Q);
	for (int i = 0; i < len; i++) 
	{
		int e;
		DeQueue(Q, e);
		printf("%d ", e);
	}
}

int main() 
{
	SqQueue Q;

	if (InitQueue(Q)) 
	{
		printf("队列初始化成功!\n");
	}
	else 
	{
		printf("队列初始化失败!\n");
	}
	printf("队列的初始长度是:%d\n", QueueLength(Q));

	// 入队
	int n;
	printf("请输入队元素的个数:");
	scanf("%d", &n);
	for (int i = 0; i < n; i++) 
	{
		int e;
		printf("请输入第%d个元素的值:", i + 1);
		scanf("%d", &e);
		EnQueue(Q, e);
	}
	printf("队列的长度是:%d\n", QueueLength(Q));
	
	printf("遍历队列:");
	TraveQueue(Q);

	printf("\n队头元素:%d\n", GetHead(Q));

	// 出队
	for (int i = 0; i < 2; i++)
	{
		int e;
		DeQueue(Q, e);
		printf("第%d个出队元素的值:%d\n", i + 1, e);
	}
	printf("队列的长度是:%d\n", QueueLength(Q));
	
	system("pause");
	
	return 0;
}
  • 运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值