+
关于递归
+
+
什么是递归
+
+
递归(英语:Recursion),又译为递回,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。递归一词还较常用于描述以自相似方法重复事物的过程。例如,当两面镜子相互之间近似平行时,镜中嵌套的图像是以无限递归的形式出现的。也可以理解为自我复制的过程。下面这张图是递归的一种表现形式:
+

+
+
注 解释以及图片来自维基百科
+一个好玩的现象,当我们用Google搜索递归时,你会发现
+

+😅这是程序员特有的幽默么!
+
+
普通递归
+
+
关于递归的应用,我以二叉树来举例。
+
+
private BinaryTreeNode insertNextNode(BinaryTreeNode newNode, BinaryTreeNode compareNode) {
+ int result = compareNode.compareTo(newNode);
+ if (result == 0) return compareNode;
+ BinaryTreeNode nextNode = null;
+ if (result > 0) {
+ if (null == compareNode.getLeft()) {
+ compareNode.setLeft(newNode);
+ } else {
+ nextNode = compareNode.getLeft();
+ }
+ } else {
+ if (null == compareNode.getRight()) {
+ compareNode.setRight(newNode);
+ } else {
+ nextNode = compareNode.getRight();
+ }
+ }
+ return null == nextNode? compareNode : insertNextNode(nextNode, compareNode);
+}
+
+
+
上面的代码实现了对二叉树插入一个节点的操作。根据递归的定义,实现这种效果采用了递归。递归在内存中逻辑大概是这样样子:
+

+注 图片来自码农翻身
+也就是说,函数的每一次调用都会在内存中形成栈帧。如果计算机发现这个栈帧还没有执行完,或者会依赖下层栈帧,此栈帧就会一直存在。如果栈过大,则会抛出stack over flow异常。
+那上面这段代码执行的过程中,就会遇到上面所述的问题,产生这个问题的代码就在于:
+
+
return null == nextNode? compareNode : insertNextNode(nextNode, compareNode);
+
+
+
上层栈帧的返回函数(三目运算符)依赖了下层栈帧的运算,当没有执行到递归结束条件时,这样的依赖会一直存在。
+注 递归一定要有退出条件,否则就是死循环!
+那么要解决这个问题,就需要用到尾递归。
+
+
尾递归
+
+
我们对上面的代码做出修改,修改后如下:
+
+
private BinaryTreeNode insertNextNode(BinaryTreeNode newNode, BinaryTreeNode compareNode) {
+ // 前面的代码不变,这是修改了返回代码
+ if (null == nextNode) {
+ return compareNode;
+ }
+ return insertNextNode(nextNode, compareNode);
+}
+
+
+
虽然我们只是修改了返回代码,但是对于计算机来说,这就意味着上层栈帧不会依赖下层栈帧。
+
+
总结
+
+
关于递归和尾递归用愚公移山来做比喻:
+普通递归:愚公开始移山了...
+1. 他挖了一点点,但是他不搬走。他让他儿子继续挖,让他儿子告诉他还剩下多少。
+2. 他儿子挖了一点点,也不搬走,让他儿子的儿子继续挖,并且告诉他还剩下多少。
+3. 他儿子的儿子挖了一点点,也不搬走,让他儿子的儿子的儿子继续挖,并且告诉他还剩下多少。
+4. ...
+5. 当最后一个子孙挖了最后一点山,这个时候,这个子孙就会告诉他的父亲,山没啦,他的父亲告诉他的父亲...直到告诉愚公,这个时候,愚公一声令下,搬走,愚公移山就完成了。
+尾递归:愚公开始移山了...
+1. 他挖了一点点,但是他搬走了。他让他儿子继续挖,并且留下了工具。
+2. 他儿子挖了一点点,他也搬走了。他儿子让他儿子继续挖,并且也留下了工具。
+3. 他儿子的儿子挖了一点点,也搬走了,让他儿子的儿子的儿子继续挖,并且也留下了工具。
+3. ...
+4. 当最后一个子孙挖了最后一点山,山没了,愚公移山也就完成了。
+
+
+
+
diff --git a/group21/519623727/README.md b/group21/519623727/README.md
new file mode 100644
index 000000000..a1b517fd9
--- /dev/null
+++ b/group21/519623727/README.md
@@ -0,0 +1 @@
+### 大家好,这是fan的文件夹
\ No newline at end of file
diff --git a/group21/544168502/test@wanghuan b/group21/544168502/test@wanghuan
new file mode 100644
index 000000000..4a5413521
--- /dev/null
+++ b/group21/544168502/test@wanghuan
@@ -0,0 +1 @@
+test@wanghuan
\ No newline at end of file
diff --git a/group21/648084221/CainaTest/.gitignore b/group21/648084221/CainaTest/.gitignore
new file mode 100644
index 000000000..6fc499b0d
--- /dev/null
+++ b/group21/648084221/CainaTest/.gitignore
@@ -0,0 +1,24 @@
+
+*/.DS_Store
+.DS_Store
+
+
+*.xml
+*.iml
+.idea
+*.iml
+rebel.xml
+rebel-remote.xml
+
+.classpath
+.project
+.settings
+.metadata
+
+target
+*.class
+
+log
+*.log
+tmp
+*.tmp
diff --git a/group21/648084221/CainaTest/src/cc/gzhlaker/blog/ArrayList.java b/group21/648084221/CainaTest/src/cc/gzhlaker/blog/ArrayList.java
new file mode 100644
index 000000000..7e146bf4c
--- /dev/null
+++ b/group21/648084221/CainaTest/src/cc/gzhlaker/blog/ArrayList.java
@@ -0,0 +1,111 @@
+package cc.gzhlaker.blog;
+
+public class ArrayList implements List{
+ //------------------------------
+ //-Ա
+ //------------------------------
+ public int size;
+ MyData[] now;
+ //------------------------------
+ //-캯
+ //------------------------------
+ public ArrayList(){
+ size = 0;
+ now = new MyData[100];
+ }
+ public ArrayList(int length){
+ size = 0;
+ now = new MyData[length];
+ }
+ //------------------------------
+ //-߽
+ //------------------------------
+ public boolean isFill(int size,int length){
+ if(size>length){
+ return true;
+ }else if(size<=length){
+ return false;
+ }
+ return false;
+ }
+ //------------------------------
+ //-߽չ
+ //------------------------------
+ public MyData[] increaseLength(MyData[] now){
+ MyData[] newarray = new MyData[now.length+10];
+ System.arraycopy(now, 0, newarray, 0, now.length);
+ return newarray;
+ }
+
+ @Override
+ public void add(int data) {
+ if(isFill(size+1,now.length)){
+ now = increaseLength(now);
+ }
+ now[size].number = data;
+ size ++;
+ }
+
+ @Override
+ public void add(int data, int index) {
+ if(isFill(size+1,now.length)){
+ now = increaseLength(now);
+ }
+ for(int i=size+1;i>index;i--){
+ now[i].number = now[i-1].number;
+ }
+ now[index].number = data;
+ size++;
+
+
+ }
+
+ @Override
+ public void addFirst(int data) {
+ if(isFill(size+1,now.length)){
+ now = increaseLength(now);
+ }
+ for(int i=size+1;i>0;i--){
+ now[i].number = now[i-1].number;
+ }
+ now[0].number = data;
+ size++;
+ }
+
+ @Override
+ public void remove(int index) {
+ now[size].number = 0;
+ size--;
+ }
+
+ @Override
+ public void removeFirst() {
+ now[0].number = 0;
+ for(int i=0;i<=size;i++){
+ now[i].number = now[i+1].number;
+ }
+ size--;
+ }
+
+ @Override
+ public void setData(int data,int index) {
+ if(index>now.length){
+ return;
+ }
+ now[index].number = data;
+
+ }
+
+ @Override
+ public int getData(int index) {
+ if(index>now.length){
+ return -1;
+ }
+ int i = now[index].number;
+ return i;
+ }
+
+
+
+
+}
diff --git a/group21/648084221/CainaTest/src/cc/gzhlaker/blog/Linkedlist.java b/group21/648084221/CainaTest/src/cc/gzhlaker/blog/Linkedlist.java
new file mode 100644
index 000000000..34389bef7
--- /dev/null
+++ b/group21/648084221/CainaTest/src/cc/gzhlaker/blog/Linkedlist.java
@@ -0,0 +1,110 @@
+package cc.gzhlaker.blog;
+
+public class Linkedlist implements List {
+ //------------------------------
+ //-ͷΪ0
+ //------------------------------
+ //-ڲ
+ //------------------------------
+ public static class Node{
+ public int data;
+ public Node next;
+ public Node(){
+ data = 0;
+ next = null;
+ }
+ public Node(int data){
+ this.data = data;
+ next = null;
+ }
+ }
+ //------------------------------
+ //-Ա
+ //------------------------------
+ private int size;
+ Node first;
+ //------------------------------
+ //-캯
+ //------------------------------
+ public Linkedlist(){
+ first = new Node();
+ size = 0;
+ }
+ //------------------------------
+ //-ѯ
+ //------------------------------
+ public int getSize(){
+ size = first.data;
+ return size;
+ }
+
+ @Override
+ public void add(int data) {
+ Node now = first;
+ while(now.next!=null){
+ now = now.next;
+ }
+ now.next = new Node(data);
+ first.data++;
+ }
+
+ @Override
+ public void add(int data, int index) {
+ Node now = first;
+ int i = 0;
+ while(i