【程序设计思路】扳机问题的思路分析

 

 

前言

在我们设计程序时,常常会遇到这种问题:

  1. 判断一个数是否为质数。某个循环中发现因数,便确定该数为质数并结束循环体。
  2. 对一组数据冒泡排序。某个循环中发现没有元素移动,便确定这组数据排序完毕并结束循环体。

我才接触计算机不到半年,便遇到了这么多相似类型的结构,可见它的重要性和常见性。因此,我要在这篇文章中进行分析,力求在找到最合适的解决思路。首先,我要先入为主地给它命名为“扳机问题”


 

一、如何认识扳机问题?

这种问题包含一些基本特征:

  1. 具有至少一层循环。一旦满足“某种条件”立刻结束循环并获取【状态一】,反之则不断进行循环。如果进行了完整的循环,则获取【状态二】。
  2. 为了生成、判断是否满足“某种条件”,或者是进行基本的处理,程序可能会再嵌套循环体。比如冒泡排序的一轮冒泡,“某种条件”是该轮冒泡中是否进行了交换。

在对“某种条件”进行判断的前后,出现了类似于扳机的结构——箭在弦上,一触即发

for(初始状态;继续条件;进程变量){

//这里可能用于生成判断条件)

{

        基本处理;

        //可能这里也是循环体

}

//这里可能用于修改判断条件

if(条件判断){

        后续处理;

        break;

}

}

 

二、如果拆解扳机问题?

扣动扳机需要解决三个问题:扣动扳机指的是什么?这种条件从哪里来?没有扣动扳机的话怎么办?

1.扣动扳机指什么?

毫无疑问,扣动扳机意味着结束循环。那么只要分析【满足什么条件就可以结束循环】即可。

例如质数判断问题,只要发现某个数是因数就可以确定不是质数,因此成为因数就是满足条件就要扣动的扳机。如果一个数一直是质数,则可以完成循环体。

2.这种条件从哪里来?

如果是判断质数问题,只要判断该数是不是因数即可。但在冒泡排序里,必须确定一轮循环之后没有发生交换,这时就出现了思路上的不统一。

其实,我们在每次循环中都是默认没有扣动扳机的,这可以成为突破口。只要在进行一次循环体时根据触发条件设置扳机为未触发状态,在程序运行中调整触发状态,再在本次循环结束前判断是否触发了扳机即可,这会用到一个布尔类型的变量。

我们以最简单的素数判断为例:

for(int i=1; i<sqrt(n); i++){//循环体

        bool is_yinshu = false;//先未触发

        {

             if (n%i==0)    is_yinshu = true;//设为触发

        }

       if (is_yinshu)    break;//根据触发状态扣动扳机

}

这就启示我们在设计程序时,一定要注意什么是“基本循环体”,即“足以判断状态的最小循环体”。在基本操作的前后调试扳机,在操作过程中确定扳机,这样写思路比较清晰。

3.没有扣动扳机怎么办?

如果我们扣动了扳机,我们的程序就跳到了循环体之外......

如果我们没有扣动扳机,我们的程序照样走到了循环体之外......

不仅如此,如果不想在循环体外写下那个布尔类型的语句的话,循环体外也无法访问到是否扣动扳机了......

扣不扣扳机到了外面的结果都一个样啊,区别仅仅是多执行了几次循环体?如果我之后还需要这个结果呢?

我在这里想到的几种方法:

  1. 扣动扳机时解决部分问题。就是在扣动扳机的同时对一些数据进行处理,一般而言,用于要变动外部变量的数值的情况。比如,计算合数的和。这只能解决扣动扳机时顺便的问题,有局限性。
  2. 在基本循环体外面声明并定义,这样就可以将结果保留下来,再用if条件判断。这里要注意的是,if条件判断的是如果未触发会怎样怎样,而已经触发造成的后果直接在循环体内的判断里写就好了。
  3. 利用函数和返回值,这个相信大家可以理解。

//第二种方法

   bool trigger;

for(int i=1; i<sqrt(n); i++){//循环体

       trigger = false;//先未触发

        {

             if (n%i==0)    trigger  = true;//设为触发

        }

       if (trigger){   

              Things to be done;  

              break;//根据触发状态扣动扳机

             }

}

if (trigger == false) {

Things to be done;

}

 


补充

本篇文章只是讲解了这类问题的一种思路,但实际上,出现的三次关于扳机变量的检测和更新不一定只能是false-true-false,还可以是false-true-fasle,或者这两种情况的取反。例如在冒泡排序中,检测一轮冒泡有没有发生交换,就是设置move为false-true-false。只不过是前者是一触即发,一个三思后行,但都属于这种扳机问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值