《图解算法》学习笔记之递归

目录

 

1 递归从盒子中找钥匙开始

Stack Overflow:Recursion or Iteration?

2 基线条件和递归条件

3 栈

4 小结

5 试例代码

Python

C

C#

Java

JS

Matlab


1 递归从盒子中找钥匙开始

假设你在祖母的阁楼中翻箱倒柜,发现了一个上锁的神秘手提箱。

Stack Overflow上说的一句话:“如果使用循环,程序的性能可能更高;如果使用递归,程序可能
更容易理解。如何选择要看什么对你来说更重要。

Loops may achieve a performance gain for your program. Recursion may achieve a performance gain for your programmer. Choose which is more important in your situation!


Stack Overflow:Recursion or Iteration?

Comparing recursion to iteration is like comparing a phillips head screwdriver to a flat head screwdriver. For the most part you could remove any phillips head screw with a flat head, but it would just be easier if you used the screwdriver designed for that screw right?

Some algorithms just lend themselves to recursion because of the way they are designed (Fibonacci sequences, traversing a tree like structure, etc.). Recursion makes the algorithm more succinct and easier to understand (therefore shareable and reusable).

Also, some recursive algorithms use "Lazy Evaluation" which makes them more efficient than their iterative brothers. This means that they only do the expensive calculations at the time they are needed rather than each time the loop runs.

That should be enough to get you started. I'll dig up some articles and examples for you too.

Link 1: Haskel vs PHP (Recursion vs Iteration)

Here is an example where the programmer had to process a large data set using PHP. He shows how easy it would have been to deal with in Haskel using recursion, but since PHP had no easy way to accomplish the same method, he was forced to use iteration to get the result.

http://blog.webspecies.co.uk/2011-05-31/lazy-evaluation-with-php.html

Link 2: Mastering Recursion

Most of recursion's bad reputation comes from the high costs and inefficiency in imperative languages. The author of this article talks about how to optimize recursive algorithms to make them faster and more efficient. He also goes over how to convert a traditional loop into a recursive function and the benefits of using tail-end recursion. His closing words really summed up some of my key points I think:

"recursive programming gives the programmer a better way of organizing code in a way that is both maintainable and logically consistent."

https://developer.ibm.com/articles/l-recurs/

Link 3: Is recursion ever faster than looping? (Answer)

Here is a link to an answer for a stackoverflow question that is similar to yours. The author points out that a lot of the benchmarks associated with either recursing or looping are verylanguage specific. Imperative languages are typically faster using a loop and slower with recursion and vice-versa for functional languages. I guess the main point to take from this link is that it is very difficult to answer the question in a language agnostic / situation blind sense.

Is recursion ever faster than looping?

2 基线条件和递归条件

编写递归函数时,必须告诉它何时停止递归。正因为如此, 每个递归函数都有两部分:基线
条件(base case)和递归条件(recursive case) 。递归条件指的是函数调用自己,而基线条件则
指的是函数不再调用自己,从而避免形成无限循环。
 

def countdown(i):
    print(i)
    if i <= 0:
        return
    else:
        countdown(i-1)


countdown(5)

3 栈

调用另一个函数时,当前函数暂停并处于未完成状态。该函数的所有变量的值都还在内存中。
 

def countdown(i):
    # print(i)
    if i == 1:
        return 1
    else:
        return i*countdown(i-1)


print(countdown(3))

注意,每个fact调用都有自己的x变量。在一个函数调用中不能访问另一个的x变量。
 

4 小结
 


 递归指的是调用自己的函数。
 每个递归函数都有两个条件:基线条件和递归条件。
 栈有两种操作:压入和弹出。
 所有函数调用都进入调用栈。
 调用栈可能很长,这将占用大量的内存。
 

5 试例代码

Python

def greet2(name):
    print("how are you, ", name, "?")

def bye():
    print("ok bye!")

def greet(name):
    print("hello, ", name, "!")
    greet2(name)
    print("getting ready to say bye...")
    bye()

greet("adit")
def fact(x):
  if x == 1:
    return 1
  else:
    return x * fact(x-1)

print(fact(5))

C

#include <stdio.h>

void countdown(int i) {
	printf("%d\n", i);

	// base case
	if (i <= 0)
		return;
	//recursive case
	else
		countdown(i - 1);
}

int main(void) {

	countdown(5);

	return 0;
}
#include <stdio.h>

void greet2(char *name) {
	printf("how are you, %s?\n", name);
}

void bye() {
	printf("ok bye!\n");
}

void greet(char *name) {
	printf("hello, %s!\n", name);
	greet2(name);
	printf("getting ready to say bye...\n");
	bye();
}

int main(void) {
	
	greet("adit");

	return 0;
}
#include <stdio.h>

int fact(int x) {
	if (x == 1)
		return 1;
	else
		return x * fact(x - 1);
}

int main(void) {

	printf("%d", fact(5));

	return 0;
}

C#

using System;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine(Fact(5));
        }

        private static int Fact(int x)
        {
            if (x <= 1) return 1;

            return x * Fact(x - 1);
        }
    }
}

Java


public class Countdown {

    private static void countdown(int i) {
        System.out.println(i);

        // base case
        if (i <= 0) {
            return;
        } else {
            countdown(i - 1);
        }
    }

    public static void main(String[] args) {
        countdown(5);
    }
}
public class Factorial {

    private static int fact(int x) {
        if (x == 1) {
            return 1;
        } else {
            return x * fact(x - 1);
        }
    }

    public static void main(String[] args) {
        System.out.println(fact(5));
    }
}

JS


function countdown(i) {
  console.log(i);
  // base case
  if (i <= 0) {
    return;
  } else {
    countdown(i-1);
  }
}

countdown(5);
function greet2(name) {
  console.log('how are you, ' + name + '?');
}

function bye() {
  console.log('ok bye!');
}

function greet(name) {
  console.log('hello, ' + name + '!');
  greet2(name);
  console.log('getting ready to say bye...');
  bye();
}

greet('adit');
function fact(x) {
  if (x === 1) {
    return 1;
  } else {
    return x * fact(x-1);
  }
}

console.log(fact(5));

Matlab

function f=factial(n)
if n==0
f=10;
elseif n>=1
f=n*factial(n-1);
end

猜你喜欢

转载自blog.csdn.net/moonlightpeng/article/details/88383207