递归.像蜗牛一样一步一步往上爬

递归这个点我写了很久,三天都在写递归的图形,写的真的有点心烦,第三天还没与写出来的时候,我坐在咖啡厅的角落里鄙视了一下自己的时候那颗玻璃心碎了一地,差点就要落下热泪。那天晚上,在公交车上,平时话多的我没有说话,我的小伙伴在旁边小心翼翼的安慰着我,但是那种“这个世界充满着满满的恶意”的感觉并没有消失。我们就那样安静地回到了寝室,我们告别的时候,何思对我说了一句很暖的话:“你别急,我会等你。好好休息,用好的状态去面对。”我是感动了.......(此处省略78个字)。

写递归的时候,我一直觉得我的思路很正确,我写的代码所表达的含义也很清楚明了了,但是运行的结果总是出乎意料的残酷。所以把思路细化是很关键的,同时一步步查错更是重中之重!例如在写三角递归的时候,思路就是:

1.在点击的时候先画一个三角形或矩形;

public void mouseClicked(MouseEvent e) {
        g.drawRect(s, z, w, h);
        A(s, z, w, h,j);
        if (i < 3) {
            x = e.getX();
            y = e.getY();
            g.drawLine(x, y, x, y);
            if (i == 0) {
                x = x1;
                y = y1;
            } else if (i == 1) {
                x = x2;
                y = y2;
            } else if (i == 2) {
                x = x3;
                y = y3;
            }
            i++;
        }
        g.drawLine(x1, y1, x2, y2);
        g.drawLine(x1, y1, x3, y3);
        g.drawLine(x2, y2, x3, y3);
        //j=0;
        F(x1, y1, x2, y2, x3, y3,j);// 直接放这里,不要放到主函数中去
    }

2.取三条边的中点,再调用画三角形的方法,注意坐标的变动;

public void F(int x1, int y1, int x2, int y2, int x3, int y3,int j) {
        int ex1, ex2, ex3;
    int ey1, ey3, ey2;
        j++;
        g.setColor(Color.green);
        ex1 = (x1 + x2) / 2;
        ey1 = (y1 + y2) / 2;
        ex2 = (x1 + x3) / 2;
        ey2 = (y1 + y3) / 2;
        ex3 = (x2 + x3) / 2;
        ey3 = (y2 + y3) / 2;
        g.drawLine(ex1, ey1, ex2, ey2);
        g.drawLine(ex1, ey1, ex3, ey3);
        g.drawLine(ex2, ey2, ex3, ey3);
        x2 = ex1;
        y2 = ey1;
        x3 = ex2;
        y3 = ey2;
        if(j>6) return;
        F(x1,y1, x2, y2, x3,y3,j);
         x2=x3*2-x1;
         y2=y3*2-y1;
         x1=ex3;
         y1=ey3;
         F(x1,y1,x2,y2,x3, y3,j);
         x3=x1*2-x2;
         y3=y1*2-y2;
         x2=ex1;
         y2=ey1;
        F(x1,y1, x2,y2,x3, y3,j);
        System.out.println("   " + ex1 + "  " + ey1 + "  " + ex2 + "  " + ey2
                + "  " + ex3 + "  " + ey3);
    }

写三角递归的难点就是:坐标的变动

相比较于三角的递归,矩形的递归就简单多了,因为它坐标的变动要简单一些:

public void A(int s, int z, int w, int h, int j) {
        //int ex1 , ey1;
        g.setColor(Color.blue);
        g.drawRect(s, z, w, h);
        s = s-w;
        z = z-h;
        w = w / 3;
        h = h / 3;
        g.drawRect(s, z, w, h);
        if (j > 5)return;
        A(s, z, w, h, j+1);
        s = s+4*w;
        A(s, z, w, h, j+1);
        s = s+4*w;
        A(s, z, w, h, j+1);
        z = z+4*h;
        A(s, z, w, h, j+1);
        z = z+4*h;
        A(s, z, w, h,j+1);
        s = s-4*w;
        A(s, z, w, h,j+1);
        s = s-4*w;
        A(s, z, w, h,j+1);
        z = z-4*h;
        A(s, z, w, h, j+1);
    }

运行的结果:

注意:

递归如果没有结束条件,则表示递归必须要不停的去开辟内存空间,来存储下一个要运行的方法,这样一致执行下去,内存肯定会不够使用,就会抛出堆栈内存溢出错误。
 所以必须要给递归添加一个退出的条件。
 
 什么情况下要使用递归呢?
  重复相同的工作,但是又不确定具体要重复执行的次数,就可以使用递归。

时间: 2024-10-11 07:48:01

递归.像蜗牛一样一步一步往上爬的相关文章

一步一步写算法(之递归和堆栈)

原文:一步一步写算法(之递归和堆栈) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 看过我前面博客的朋友都清楚,函数调用主要依靠ebp和esp的堆栈互动来实现的.那么递归呢,最主要的特色就是函数自己调用自己.如果一个函数调用的是自己本身,那么这个函数就是递归函数. 我们可以看一下普通函数的调用怎么样的.试想如果函数A调用了函数B,函数B又调用了函数C,那么在堆栈中的数据是怎么保存的呢? 函数A ^ 函数B | (地址递减) 函数C |

一步一步写算法(之非递归排序)

原文:一步一步写算法(之非递归排序) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在上面一篇博客当中,我们发现普通查找和排序查找的性能差别很大.作为一个100万的数据,如果使用普通的查找方法,那么每一个数据查找平均下来就要几十万次,那么二分法的查找呢,20多次就可以搞定.这中间的差别是非常明显的.既然排序有这么好的效果,那么这篇博客中,我们就对排序算做一个总结. 按照我个人的理解,排序可以分为两种:一种是非递归排序,它主要按照非递归的

一步一步写算法(之循环和递归)

原文:一步一步写算法(之循环和递归) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 其实编程的朋友知道,不管学什么语言,循环和递归是两个必须学习的内容.当然,如果循环还好理解一点,那么递归却没有那么简单.我们曾经对递归讳莫如深,但是我想告诉大家的是,递归其实没有那么可怕.所谓的递归就是函数自己调用自己而已,循环本质上也是一种递归.  1)求和递归函数 我们可以举一个循环的例子,前面我们说过,如果编写一个1到n的求和函数怎么写呢,你可能会

一步一步写jQuery插件

转载自:http://www.cnblogs.com/joey0210/p/3408349.html 前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jquery的插件机制,jquery有着成千上万的第三方插件,有时我们写好了一个独立的功能,也想将其与jquery结合起来,可以用jquery链式调用,这就要扩展jquery,写成插件形式了,如下

【转】朱兆祺带你一步一步学习嵌入式(连载)

原文网址:http://bbs.elecfans.com/jishu_357014_2_1.html#comment_top  从最初涉及嵌入式Linux开始到现在,深深的知道嵌入式的每一步学习都是举步维艰.从去年11月份开始,我就着手整理各种学习资料,希望推动嵌入式学习的前进贡献自己微不足道的一份力量.从去年到现在,将C语言的学习经验整理成<攻破C语言笔试与机试陷阱及难点>(现在仍在更新),这份资料已经在电子发烧友论坛的单片机论坛连载(http://bbs.elecfans.com/jish

一步一步写平衡二叉树(AVL树)

平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树.平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态.这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(

一步一步写二叉查找树

二叉查找树(BST)是二叉树的一个重要的应用,它在二叉树的基础上加上了这样的一个性质:对于树中的每一个节点来说,如果有左儿子的话,它的左儿子的值一定小于它本身的值,如果有右儿子的话,它的右儿子的值一定大于它本身的值. 二叉查找树的操作一般有插入.删除和查找,这几个操作的平均时间复杂度都为O(logn),插入和查找操作很简单,删除操作会复杂一点,除此之外,因为二叉树的中序遍历是一个有序序列,我就额外加上了一个中序遍历操作. 二叉查找树的应用不是很多,因为它最坏的时候跟线性表差不多,大部分会应用到它

一步一步写算法(之排序二叉树)

原文:一步一步写算法(之排序二叉树) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点.它是这样定义的: typedef struct _TREE_NODE { int data; struct _TREE_NODE* parent; str

一步一步认识C++STL中的迭代器

一步一步认识C++STL中的迭代器 "指针"对所有C/C++的程序员来说,一点都不陌生.在接触到C语言中的malloc函数和C++中的new函数后,我们也知道这两个函数返回的都是一个指针,该指针指向我们所申请的一个"堆".提到"堆",就不得不想到"栈",从C/C++程序设计的角度思考,"堆"和"栈"最大的区别是"栈"由系统自动分配并且自动回收,而"堆&quo

一步一步写算法(之堆排序)

原文:一步一步写算法(之堆排序) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 堆排序是另外一种常用的递归排序.因为堆排序有着优秀的排序性能,所以在软件设计中也经常使用.堆排序有着属于自己的特殊性质,和二叉平衡树基本是一致的.打一个比方说,处于大堆中的每一个数据都必须满足这样一个特性: (1)每一个array[n] 不小于array[2*n] (2)每一个array[n]不小于array[2 * n + 1] 构建这样一个堆只是基础,后