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

来源:互联网 发布:python 加减法 编辑:程序博客网 时间:2024/06/11 11:31

上一节说了递归控制,最后分析了递归函数的缺点,我们现在使用循环控制将递归函数进行改造,使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天)就更新的,结果实验室来个个临时项目,估计要花点时间了~

原创粉丝点击