(二)栈、队列、链表—— 1. 队列

1. 解密QQ号——队列

给出一串加密过的数字,解密规则如下:

首先将第 1 个数删除,紧接着将第 2 个数放到这串数的末尾,再将第 3 个数删除并将第 4 个数放到这串数的末尾,以此类推… 直到剩下最后一个数,将最后一个数也删除。

按照刚才删除的顺序,把这些删除的数连在一 起就是最终结果。

例如,加密过的一串数是“6 3 1 7 5 8 9 2 4”。那么,结果为:6 1 5 9 4 7 2 8 3。


1.1 编程思想

首先需要一个数组来存储这一串数即 int q[101],并初始化这个数组即 int q[101]= {0,6,3,1,7,5,8,9,2,4};
(此处初始化多写了一个 0,用来填充 q[0],从 q[1] 开始用)

解密的第一步是将第一个数删除,最简单的方法是将所有后面的数都往前面挪动一位,将前面的数覆盖。但是这样的做法很耗费时间。

在这里,将引入两个整型变量 head 和 tail。head 用来记录队列的队首(即第一位), tail 用来记录队列的队尾(即最后一位)的下一个位置。

为什么 tail 不直接记 录队尾,却要记录队尾的下一个位置呢?

这是因为当队列中只剩下一个元素时,队首和队尾重合会带来一些麻烦。这里规定队首和队尾重合时,队列为空。

现在有 9 个数,9 个数全部放入队列之后 head=1;tail=10;此时 head 和 tail 之间的数就是目前队列中“有效”的数。

在队首删除一个数的操作是 head++;。

在队尾增加一个数(假设这个数是 x)的操作是 q[tail]=x;tail++;。

解密过程,如下图所示:


1.2 代码实现

#include <stdio.h>

int main() {
    int q[102]={0, 6, 3, 1, 7, 5, 8, 9, 2, 4}, head, tail;
    //初始化队列
    head = 1;
    tail = 10; //队列中已经有9个元素了,tail指向队尾的后一个位置
    while (head < tail) //当队列不为空的时候执行循环
    {
    	//打印队首并将队首出队
        printf("%d", q[head]);
        head++;
        //先将新队首的数添加到队尾
        q[tail] = q[head];
        tail++;
        //再将队首出队
        head++;
    }
    getchar();getchar();
    return 0;
}

1.3 基本概念

1.3.1 队列

队列是一种特殊的线性结构,它只允许在队列的首部(head)进行删除操作,这称为**“出队”,而在队列的尾部(tail)进行插入操作,这称为“入队”**。

当队列中没有元素时(即 head==tail),称为空队列

在我们的日常生活中有很多情况都符合队列的特性。比如买票, 每个排队买票的窗口就是一个队列。在这个队列当中,新来的人总是站在队列的最后面,来得越早的人越靠前,也就越早能买到票,就是先来的人先服务,称为“先进先出”(First In First Out,FIFO)原则。


1.3.2 结构体

现在将队列的三个基本元素(一个数组,两个变量)封装为一个结构体类型, 如下:

struct queue
{
	int data[100]; //队列的主体,用来存储内容
	int head; //队首
	int tail; //队尾
};

上面定义了一个结构体类型,通常将其放在 main 函数的外面。

struct 是结构体的关键字,queue 是为这个结构体起的名字。

这个结构体有三个成员分别是:整型数组 data、整型 head 和整型 tail。这样我们就可以把这三个部分放在一起作为一个整体来对待。

可以这么理解:
定义了一个新的数据类型,这个新类型非常强大,用这个新类型定义出的每一个变量可以同时存储一个整型数组和两个整数。


有了新的结构体类型,定义结构体变量与之前定义变量的方式 是一样的,具体做法如下:

struct queue q;

其中,struct queue 需要整体使用,不能直接写 queue q;。

这样我们就定义了一个结构体变量 q。


如何访问结构体变量的内部成员呢?可以使用.号,它叫做成员运算符或者点号运算符,如下:

q.head = 1;
q.tail = 1;
scanf("%d", &q.data[q.tail]);

使用结构体来实现的队列操作:

#include <stdio.h>

struct queue
{
	int data[100];//队列的主体,用来存储内容
	int head;//队首
	int tail;//队尾
	
};

int main() {
	struct queue q;
	int i;
	//初始化队列
	q.head = 1;
	q.tail = 1;
	for (i=1; i<=9; i++) {
		//依次向队列插入9个数
		scanf("%d", &q.data[q.tail]);
		q.tail++;
	}
	while (q.head < q.tail) //当队列不为空的时候执行循环
	{
		//打印队首并将队首出队
		printf("%d ", q.data[q.head]);
		q.head++;
		//先将新队首的数添加到队尾
		q.data[q.tail] = q.data[q.head];
		q.tail++;
		//再将队首出队
		q.head++;
	}
	getchar();getchar();
	return 0;
}

输入数据:
6 3 1 7 5 8 9 2 4

返回值:
6 1 5 9 4 7 2 8 3





参考

《啊哈!算法》 —— 第2章 栈、队列、列表

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值