Answers:
这里有很多数学示例,但是您需要一个真实的示例,因此,经过一番思考,这可能是我可以提供的最好的示例:
您发现感染了致命性给定的球菌感染并迅速修复的人(A型),只有五分之一的人(被称为B型)被永久性感染,但没有症状,只是充当传播者。
当类型B感染大量类型A时,这会造成非常令人讨厌的破坏波。
您的任务是追踪所有B型B并免疫以阻止疾病的骨干。不幸的是,您无法对所有人实行全国范围的治疗,因为A型患者对B型治疗也具有致命的过敏性。
您可以通过社交发现的方式进行操作,给定一个受感染的人(A型),选择上周的所有联系人,并在堆上标记每个联系人。当您测试某个人被感染时,请将其添加到“跟进”队列中。当一个人是B型时,请将其添加到头部的“跟进”中(因为您想快速停止)。
在处理了给定的人之后,从队列的前面选择该人并根据需要进行免疫接种。获取以前未访问过的所有联系人,然后进行测试以查看是否被感染。
重复此操作,直到被感染人员的队列变为0,然后等待下一次爆发。
(好吧,这有点迭代,但是它是解决递归问题的一种迭代方式,在这种情况下,尝试遍历人口基数以尝试发现问题的可能路径,此外,迭代解决方案通常更快,更有效,而且我强迫性地在所有地方都取消了递归,这本能地.....该死!
文件系统中涉及目录结构的所有内容如何。递归查找文件,删除文件,创建目录等。
这是一个Java实现,它递归地打印目录及其子目录的内容。
import java.io.File;
public class DirectoryContentAnalyserOne implements DirectoryContentAnalyser {
private static StringBuilder indentation = new StringBuilder();
public static void main (String args [] ){
// Here you pass the path to the directory to be scanned
getDirectoryContent("C:\\DirOne\\DirTwo\\AndSoOn");
}
private static void getDirectoryContent(String filePath) {
File currentDirOrFile = new File(filePath);
if ( !currentDirOrFile.exists() ){
return;
}
else if ( currentDirOrFile.isFile() ){
System.out.println(indentation + currentDirOrFile.getName());
return;
}
else{
System.out.println("\n" + indentation + "|_" +currentDirOrFile.getName());
indentation.append(" ");
for ( String currentFileOrDirName : currentDirOrFile.list()){
getPrivateDirectoryContent(currentDirOrFile + "\\" + currentFileOrDirName);
}
if (indentation.length() - 3 > 3 ){
indentation.delete(indentation.length() - 3, indentation.length());
}
}
}
}
Quicksort,merge sort和大多数其他N-log N个排序。
马特·迪拉德(Matt Dillard)的榜样很好。更一般地,树的任何行走通常都可以非常容易地通过递归来处理。例如,编译解析树,遍历XML或HTML等。
当然,那里的许多编译器都大量使用递归。计算机语言本身具有递归性(例如,您可以将“ if”语句嵌入其他“ if”语句中,等等)。
对容器控件中的所有子控件禁用/设置只读。我需要这样做,因为某些子控件是容器本身。
public static void SetReadOnly(Control ctrl, bool readOnly)
{
//set the control read only
SetControlReadOnly(ctrl, readOnly);
if (ctrl.Controls != null && ctrl.Controls.Count > 0)
{
//recursively loop through all child controls
foreach (Control c in ctrl.Controls)
SetReadOnly(c, readOnly);
}
}
(来源:mit.edu)
这是eval的定义:
(define (eval exp env)
(cond ((self-evaluating? exp) exp)
((variable? exp) (lookup-variable-value exp env))
((quoted? exp) (text-of-quotation exp))
((assignment? exp) (eval-assignment exp env))
((definition? exp) (eval-definition exp env))
((if? exp) (eval-if exp env))
((lambda? exp)
(make-procedure (lambda-parameters exp)
(lambda-body exp)
env))
((begin? exp)
(eval-sequence (begin-actions exp) env))
((cond? exp) (eval (cond->if exp) env))
((application? exp)
(apply (eval (operator exp) env)
(list-of-values (operands exp) env)))
(else
(error "Unknown expression type - EVAL" exp))))
这是apply的定义:
(define (apply procedure arguments)
(cond ((primitive-procedure? procedure)
(apply-primitive-procedure procedure arguments))
((compound-procedure? procedure)
(eval-sequence
(procedure-body procedure)
(extend-environment
(procedure-parameters procedure)
arguments
(procedure-environment procedure))))
(else
(error
"Unknown procedure type - APPLY" procedure))))
这是评估序列的定义:
(define (eval-sequence exps env)
(cond ((last-exp? exps) (eval (first-exp exps) env))
(else (eval (first-exp exps) env)
(eval-sequence (rest-exps exps) env))))
eval
-> apply
-> eval-sequence
->eval
递归应用于问题(情况),您可以将其分解(减少)成较小的部分,每个部分看起来都类似于原始问题。
包含与自己相似的较小部分的事物的很好的例子是:
递归是一种将问题不断分解为越来越小的技术,直到其中一个变得足够小以至于成为小菜一碟。当然,将它们分解后,您必须按照正确的顺序将结果“缝合”在一起,以形成原始问题的整体解决方案。
一些递归排序算法,树遍历算法,地图/归约算法,分治法都是该技术的示例。
在计算机编程中,大多数基于堆栈的调用返回类型语言已经具有内置的递归功能:即
在函数式编程语言中可以找到一些很好的递归示例。使用函数式编程语言(Erlang,Haskell,ML / OCaml / F#等)中,使用递归进行任何列表处理是很常见的。
当使用典型的命令式OOP风格的语言处理列表时,通常会看到将列表实现为链接列表([item1-> item2-> item3-> item4])。但是,在某些函数式编程语言中,您发现列表本身是递归实现的,其中列表的“头”指向列表中的第一项,而“尾部”指向包含其余项的列表( [item1-> [item2-> [item3-> [item4-> []]]]])。我认为这非常有创意。
与模式匹配结合使用时,列表的这种处理功能非常强大。假设我想对数字列表求和:
let rec Sum numbers =
match numbers with
| [] -> 0
| head::tail -> head + Sum tail
本质上说:“如果使用空列表调用我们,则返回0”(允许我们中断递归),否则返回head的值+与其余项调用的Sum的值(因此,我们的递归)。
例如,我可能有一个URL列表,我认为将每个URL链接到的所有URL分开,然后减少到/来自所有URL的链接总数,以为页面生成“值”(这种方法是Google与PageRank一起使用,您可以在原始MapReduce论文中找到定义)。您也可以执行此操作以在文档中生成字数统计。还有很多很多其他的东西。
您可以将此功能模式扩展到任何类型的MapReduce代码,在其中可以获取内容列表,进行转换并返回其他内容(无论是其他列表还是列表上的某些zip命令)。
XML,或遍历任何树。虽然,老实说,我几乎从未在工作中使用递归。
假设您正在为网站构建CMS,其中您的页面是树状结构,并且说根是主页。
假设您的{user | client | customer | boss}要求您在每个页面上放置一个面包屑痕迹,以显示您在树中的位置。
对于任何给定的页面n,您可能需要递归到n的父级及其父级,依此类推,以递归的方式建立一个节点列表,以返回到页面树的根目录。
当然,在该示例中,您在每个页面上多次击中数据库,因此您可能需要使用一些SQL别名,在其中将page-table查找为a,然后将page-table查找为b,然后将a.id与b.parent,以便您使数据库执行递归联接。已经有一段时间了,所以我的语法可能没有帮助。
再一次,您可能只想计算一次并将其与页面记录一起存储,仅在移动页面时才对其进行更新。那可能会更有效率。
无论如何,那是我的$ .02
我知道的最好的例子是quicksort,它与递归相比要简单得多。看一眼:
shop.oreilly.com/product/9780596510046.do
www.amazon.com/zh-CN/Beautiful-Code-Leading-Programmers-Practice/dp/0596510047
(单击第3章“我写过的最漂亮的代码”下的第一个字幕)。