编程思想(技巧)---循环控制

上一节说了递归控制,最后分析了递归函数的缺点,我们现在使用循环控制将递归函数进行改造,使stack的压力减小,提高程序的运行效率。

循环控制要点:

1.循环不变式(loop invariant)

循环不变式是一句断言定义各变量所需满足的条件,在写循环控制的时候需要重点思考,这么说太抽象,具体看后面例题~

2.循环书写方法:

  • 定义循环不变式,并在循环体每次结束后保持循环不变式
  • 先一般,后特殊
  • 每次必须向前推进循环不变式中涉及的变量值
  • 每次推进的规模必须为1
  • 编写时假设已经循环了很多次,思考下一次该怎么循环,而不是思考第一次应该怎么循环

3.技巧:

把问题切开,假设一部分已经完成,一部分未完成,思考下一步如何往前推进。

例子1:链表反转

上节中的链表反转使用递归实现,假设链表有一万活着更多元素,运行起来效率极低,而且还有stackoverflow的问题,使用循环实现,效率很高。
思路分析如图:
这里写图片描述

我们将链表逻辑分开,假设链表左边已经完成了反转,右边没有完成反转,那么只需要思考下一步我怎么把值为3的这个节点反转,我们只需要将currentHead节点指向newHead节点,并将currentHead节点和newHead向后移动即可。完成后,在判断一些边界条件,在while循环中思考如何去除边界条件和退出循环。

我们具体看代码分析:

public class LinkedListReverser {
    public Node reverseLinkedList(Node head){
        Node newHead = null;
        Node curHead = head;
        //loop invariant
        //newHead points to the linked list already reversed
        //curHead points to the linked list not yet reversed
        while (curHead!=null){
            //loop invariant holds.
            Node next = curHead.getNext();
            curHead.setNext(newHead);
            newHead = curHead;
            curHead = next;
        }
        //loop invariant holds.
        return newHead;
    }
}
例子2:删除链表中的某个元素

题目如图:
这里写图片描述

我们现在要把链表中的节点值为2的节点删除,思路不变,首先假设左边某部分的链表意见删除完毕(比如3节点旁边的2),下面思考如何删除右边部分的节点,我们首先需要判断3右边的节点是否为2,若是,则将指针指向下一个节点,这样就实现了删除该节点,如果3右边节点不是2,next直接指向右边的节点即可。需要思考的是一些边界条件,比如链表为空,或者链表第一个节点就为要删除的元素等等,使用while、if循环处理边界情况。

代码实现如下:

public class LinkedListDeletor {
    public Node deleteIfEquals(Node head,int value){
        while (head.getValue()==value){
            head = head.getNext();
        }
        if (head==null){
            return null;
        }
        Node prev = head;
        //loop invariant:list nodes from head up to prev has been
        //processed.(Nodes with values equals to value are deleted)
        while (prev.getNext()!=null) {
            if (prev.getNext().getValue()==value){
                //delete it
                prev.setNext(prev.getNext().getNext());
            }else {
                prev = prev.getNext();
            }
        }
        return head;
    }
}

只要明确了循环不变式,了解了边界条件,写一个循环控制的程序也就不难了,而且循环控制有很多好处,但是循环函数也不是万能的,很多问题无法解决,需要我们具体问题具体分析。下一节是一些关于边界控制的考虑问题。

ps:本打算每天(至少2天)就更新的,结果实验室来个个临时项目,估计要花点时间了~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值