以史为鉴C实践之四:区域填充函数(递归调用)

实现函数

int fillregion(char *buf, int x, int y)
/*描述:
	依次检查坐标(x,y)周围的邻居点,最多8个邻居点,注意边界
	如果该邻居为0,则将该邻居的值修改为1,
	并使用该邻居坐标,递归调用fillregion
	返回值:返回0
	*/

实现效果预测

由于源文件是这样的文件:
在这里插入图片描述
在加上第二篇文章前面改为pbm的效果,会呈现出test.pbm的图片
在这里插入图片描述

在这里插入图片描述
实际上按照猜想,我认为,由于数据1代表的是黑方块,而数据0代表的是白方块,那么这个函数的作用将会是:指定一个坐标,将这个坐标的邻居点的白方块改为黑方块,并将邻居点作为新坐标,进行以上操作,直至邻居点上没有白方块为止。

实现思路

实际上,经过前面的test1.txt冗余处理,那么,就只剩下一个由0,1构成的一位数组。如果函数形参的是(x,y)的坐标的话,首先要做的是,如何将(x,y)转化为一位数组上面可以处理的坐标?
第二,实现邻居点的判断和修改?
第三,实现(x,y)转为邻居点,并进行递归调用。直到不满足递归条件(即邻居点全为‘1’)为止。

问题解决:

  1. 为实现坐标转化为一维数组的索引,假设将2500个数字转化为50*50的方阵,坐标x为0-49,坐标y为0-49,那么坐标(x,y)与索引值idx的关系为:

idx = 50*x + y;

  1. 实现邻居点判断和修改:理论上,应该最多有8个邻居点,但由于边界的问题,8个邻居点当中有些点会不存在。此时只需判断{邻居点x∈[0,49],邻居点y∈[0,49]则可知此点是否合法。
  2. 实现递归调用,搞明白递归何时进入、何时退出、递归的条件。

伪代码

int fillregion(char *buf, int x, int y) //用函数fillregion实现区域填充
BLOCK 1 //将(x,y)坐标转化为一维数组索引idx
BEGIN
	一维数组索引值 idx = 50*x + y;
END
BLOCK 2 //区域填充,递归调用
	IF 一号邻居点合法
	{
		一号邻居索引idx_1 = BLOCK 1(一号);
		IF 一号邻居点值为'0',即buf[idx_1] = '0'
		{
			令buf[idx_1] = '0';
			fillregion(char *buf, (一号坐标));
		}
	}
	二号至八号邻居点重复以上过程;
END

实现效果

在经过篇目三的readfile以及trim读取buf以及去除冗余后,通过fillregion以及writefile,得到最后的图片效果如下:

int main()
{
bytes = readfile(filename, buf);
bytes = trim(buf, bytes);
fillregion(char *buf, int x, int y);
writefile(new_filename, header,
header_len);
writefile(new_filename,
buf, bytes);

在这里插入图片描述

主要问题以及解决方案

关于C语言的递归函数

递归函数实际上执行过程有:回溯和递推两个过程,将会逐层进入,逐层退出。以下连接有具体例子:C语言递归函数
注意:每个递归只能进行有限次调用,否则会进入死胡同,永远退不出。故需要:限制条件,每次递归调用之后越来越接近这个限制条件。

关于递归函数效率问题

在实现递归的时候,时间和空间上开销比较大,但符合人们的思路,程序容易理解,可以不考虑递归过程的细节,只需写出递归公式以及边界条件。如果有的函数需要频繁调用,用时长,希望尽量压缩时间开销。
C++提供了一种高效的方法,即内置函数(inline function),即在编译时将所调用的函数代码直接嵌入到主函数当中,而不是将流程转出去。但是内置函数只能在函数规模很小,且不包含复杂控制语句的情况下使用。

堆栈深度

刚开始的时候,把buf放在main函数里面了,导致函数递归调用的时候深度很大,导致栈溢出。后来将数组改为全局变量,才解决了这个问题。
反映的首先是,在写程序的时候,几乎不考虑时间以及空间效率的问题,其二,对于变量的内存等问题不够了解,导致出现以上错误。
另外,对于递归,必须考虑到栈容量的压力,优化C++程序的效率,是精益求精的体现。
后续将更加具体地去深挖这方面的知识。
C语言的变量如何在内存中分部。C语言有全局变量、本地变量、静态变量、寄存器变量,每种变量都有不同的分配方式。
全局变量和静态变量分配的内存时连续的,而它们和本地变量分配的内存地址差了很远。
对于一个内存空间而言,可以在逻辑上分为3个部分:代码区、静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈”和“堆”时两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。
全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值