Java常用算法——迭代 & 递归篇

迭代 & 递归

迭代

(1).定义

来自维基百科:

迭代是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果。每一次对过程的重复被称为一次”迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。

在数学中:
数学中的迭代可以指函数迭代的过程,即反复地运用同一函数计算,前一次迭代得到的结果被用于作为下一次迭代的输入。即使是看上去很简单的函数,在经过迭代之后也可能产生复杂的行为,衍生出具有难度的问题。这样的例子可以参见考拉兹猜想和杂耍者序列(Juggler sequence)。又如一个简单的二次变换x→x(1-x),它的迭代将形成一个具有混沌性质的动力系统。
迭代在数学中的另一应用是迭代法,用来对特定数学问题作数值解估计。牛顿法就是迭代法的一个例子。

在计算机中:
在计算机科学中,迭代是程序中对一组指令(或一定步骤)的重复。它既可以被用作通用的术语(与”重复”同义),也可以用来描述一种特定形式的具有可变状态的重复。
在第一种意义下,递归是迭代的一个例子,但是通常使用一种递归式的表达。比如用0!=1n!=n\*(n-1)!来表示阶乘。而迭代通常不是这样写的。
而在第二种(更严格的)意义下,迭代描述了在指令式编程语言中使用的编程风格。与之形成对比的是递归,它更偏向于声明式的风格。

这里是一个依赖于破坏性赋值的迭代的例子,以指令式的虚拟码写成:

 var i, a = 0        // 迭代前初始化
 for i from 1 to 3    // 循环3次
 {  
     a = a + i       // a的值增加i
 }
 print a              // 打印出数字6

在这个程序片段中,变量i的值会不断改变,依次取值1、2和3。这种改变赋值——或者叫做可变状态——是迭代的特征。

(2).示例

迭代的概念不难理解,下面是一个迭代的小例子

牛顿迭代法:

r f(x)=0 的根,选取 x0 作为r的初始近似值,过点( x0 f(x0) )做曲线 y=f(x) 的切线L,L的方程为 y=f(x0)+f(x0)(xx0) ,求出L与x轴交点的横坐标 x1=x0f(x0)f(x0) ,称 x1 r的一次近似值。过点( x1 f(x1) )做曲线 y=f(x) 的切线,并求该切线与x轴交点的横坐标 x2=x1f(x1)f(x1) ,称 x1 r的二次近似值。重复以上过程,得r的近似值序列,其中, xn+1=xnf(xn)f(xn) 称为rn+1次近似值,上式称为牛顿迭代公式。

用牛顿迭代法解非线性方程,是把非线性方程 f(x)=0 线性化的一种近似方法。把 f(x) 在点 x0 的某邻域内展开成泰勒级数:

f(x)=f(x0)+f(x0)(xx0)+f(x0)(xx0)22!+...+f(n)(x0)(xx0)nn!+Rn(x)

取其线性部分(即泰勒展开的前两项),并令其等于0,即 f(x0)+f(x0)(xx0)=0 ,以此作为非线性方程 f(x)=0 的近似方程,若 f(x0)0 ,则其解为 x1=x0f(x0)f(x0)
这样,得到牛顿迭代法的一个迭代关系式: xn+1=xnf(xn)f(xn)

图示:

这里写图片描述
因此,有了以上的知识预备之后,我们就可以利用牛顿迭代法求算术平方根了。即求 x2a=0 的正根。
则令 f(x)=x2a 因此 f(x) 求一阶导的结果为:
      

f(x)=2x

而牛顿迭代式为:
      
xn+1=xnx2na2xn=12(xn+axn)

因此可以任意指定一个迭代的初始值,例如 x0=1 ,代入上面的式子迭代。
例如计算 2 ,即此时 a=2
x0=1
x1=12(1+21)=1.5
x2=12(1.5+21.5)=1.4166...
...
因此我们在计算的时候可以设置一个迭代终止条件,即设置精度,这样的话得到的结果即是精度范围内的近似结果,可用如下方式设置精度:
(xxa)a<=(1e6)

因此当误差小于指定精度时,则停止迭代。
小例子:

package month12.day12;

import java.util.Scanner;

/**
 * Created by Administrator on 2016/12/12.
 */
public class TestForSqrt {
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextInt()) {
            int number = scanner.nextInt();
            double x = 1;
            do {
                x = 0.5 * (x + number / x);
            }while ((x * x - number) / number > 1e-6);
            System.out.println("The NewTon Method solve:" + number + "\'s sqrt is:" + x);
            System.out.println("The Math class's static method solve: " + number + "\'s sqrt is:" + Math.sqrt(number)); //number自动类型提升至double传入sqrt()方法
        }
    }
}
延伸:【用牛顿迭代法开任意次方】

ak 的递推式为:
      

xn+1=xnxknakxk1n=k1kxn+akxk1n

递归

(1).定义

来自维基百科:

递归(英语:recursion)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。

[1] 递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。

[2] 绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全替换循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。

(2).示例
1.阶乘问题

对于阶乘问题,显然可以给出如下定义:

n!={1n(n1)!if n = 0if n  1 

这样的话,就将一个 n阶问题转化成了一个 n-1阶的问题。而问题的”出口”即为 n == 0时,当问题分解至 n == 0,则可将子问题的结果一层一层迭代回其原问题,直至得出最后的结果返回主函数。示例代码:

package month12.day12;

import java.util.Scanner;

/**
 * Created by Administrator on 2016/12/12.
 */
public class TestForFac {
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLong()) {
            long number = scanner.nextLong();
            System.out.println(number + "! = " + fac(number));
        }
    }
    static long fac(long num) {
        if (num == 0) {
            return 1;
        } else {
            return num * fac(num - 1);
        }
    }
}

程序运行结果:

4
4! = 24
3
3! = 6
5
5! = 120
0
0! = 1

另外可以模拟递归分解问题以及迭代回原问题的过程,加深对递归的理解,如下:

#include <stdio.h>

int Fib(int n, int step) {
    if (n == 1) {
        return 1;
    } else {
        int temp = step;
        while (temp--) {
            printf("  ");
        }
        printf("%dx%d!\n", n, n - 1);
        int value = Fib(n - 1, step + 1);
        temp = step;
        while (temp--) {
            printf("  ");
        }
        printf("%dx%d\n", n, value);
        return n * value;
    }
}

int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        printf("%d\n", Fib(n, 0));
    }
    return 0;
}

程序运行结果:
这里写图片描述

2.汉诺塔问题

汉诺塔是根据一个传说形成的数学问题:
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
    每次只能移动一个圆盘;
    大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?

根据问题提示,很容易想到,我在移动n个圆盘的时候,由于大盘不能叠在小盘上面,所以我肯定想怎么样能先把最后一个盘子移到C杆去,这样的话就不用再管最大的那个盘子了。那么顺着这样的思路,我要把最后一个盘子移到C杆去,那这最后一个大盘子上的n-1个盘子要先移开才行。这n-1个盘子移开之后,然后我就可以把最后一个盘子(也就是最大的那个)移到C杆去。所以我可以先用B杆,帮我先”暂存”这上面的n-1个盘子。但是每次只能移动一个圆盘,所以我要借助剩下的杆子,也就是C杆,来协助把这n-1个盘子移到B杆上,然后才能把最大的盘子移到C杆上面去。当把最大的盘子移到C杆之后,剩下的问题就简单了,我只需要将剩下的n-1个盘子移到C杆就完成目标了(同样要借助剩下的杆子)。问题分析完毕,那么用简略的语言总结一下:

首先,以A杆作为起始杆,借助C杆作为中间杆(起协助作用),将n-1个盘子移至B杆;
其次,将底下”最大的盘子”从A杆(起始杆)移至C杆(目标杆);
最后,以B杆作为起始杆,借助A杆作为中间杆(起协助作用),将n-1个盘子移至C杆;

而核心问题来了,每次只能移动一个圆盘,所以第一步移动n-1个盘子移至B杆的操作显然是不能一蹴而就的,除非当n-1等于1的时候,就可以直接移动了,因此第一步移动n-1个盘子移至B杆的操作还要继续分解,直至分解成可以直接操作的子问题。而该问题的分解过程与上述过程完全一致,因此依旧是递归这个过程分解原问题。同样的,最后一步的过程以此类推。这样,原问题就被分解成两个n-1阶的子问题和一个1阶的子问题。下面用简单的数学语言概括一下(设n阶汉诺塔问题为 f(n) ),即为:

f(n)={12f(n1)+1if n = 1if n  1 

下面简单证明为什么这样的做法是步数最小的做法:

数学归纳法证明过程如下:

n == 1,结果显然为1。

假设 f(n1) 确实是把n-1个盘子集体挪动的最小步数,我们要证明 f(n) 是把n个盘子集体挪动的最小步数。

1.在把n个盘子从A移动到C的过程中,必然存在一步,是把最大的盘子从A拿出来。要想把最大的盘子从A移动到别的某个柱子上(B或C),就必须保证剩下的n-1个盘子先移走,得好好堆在剩下那个柱子(C或B)上。要保证n-1个盘子都在剩下那个柱子上,至少得付出 f(n1) 次移动。

2.在把n个盘子从A移动到C的过程中,必然存在一步,是最大的盘子被放到了C上,而且此后再也没动过。在这步实行之前,最大的盘子要么在A要么在B上,而相应地别的n-1个盘子要么在B要么在A上。在这步实施之后,我们只要花至少 f(n1) 的步数把n-1个盘子从要么B要么A挪动到C上就行了。这些步数必然和步骤1中的步数不重叠,因为这时候最大盘子在C上,而步骤1中最大盘子在A上。

3.最大的盘子至少被挪动了一次。而且这一次肯定没被算在步骤1或步骤2的”至少 f(n1) 步”中,因为后者只挪动较小的那n-1个盘子。

综上所述: f(n) 的最小值即为: f(n)=f(n1)+1+f(n1)=2f(n1)+1
得证

有了递推公式,那么是否可以得到通项公式呢?我们观察这个式子的前几项:
f(1)=1

f(2)=2f(1)+1=3

f(3)=2f(2)+1=2(2f(1)+1)+1=22f(1)+211+1(20)=231=7

f(4)=2f(3)+1=2(2f(2)+1)+1=22f(2)+211+1(20)=22(2f(1)+1)+211+20=241=15

...
很显然,这是一个等比数列的求和问题,则:
f(n)=20+21+22+...+2n2+2n1=2n1

即得通项公式为:

f(n)=2n1

实际上,所有原问题分解成子问题的过程,用图表示的话,是一棵三叉树,最后无法再分解的子问题即为该三叉树的叶节点,而整个原问题的规模即为所有子问题的和,即该三叉树叶节点节点总数。
示例代码:

package month12.day12;

import java.util.Scanner;

/**
 * Created by Administrator on 2016/12/12.
 */
public class TestForHanoi {
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
            int number = scanner.nextInt();
            hanoi('A','B','C', number);
            System.out.println("总的步数为:" + ((1 << number) - 1));     //加减法的运算符优先级更高
        }
    }

    static void hanoi(char startPos, char transPos, char targPos, int n) {
        if (n == 1) {
            move(startPos, targPos);
            return;
        } else {
            hanoi(startPos, targPos, transPos, n - 1);
            move(startPos, targPos);
            hanoi(transPos, startPos, targPos, n - 1);
        }
    }

    static void move(char startPos, char targPos) {
        System.out.println(startPos + " -> " + targPos);
    }
}

程序运行结果:

1
A -> C
总的步数为:1
2
A -> B
A -> C
B -> C
总的步数为:3
3
A -> C
A -> B
C -> B
A -> C
B -> A
B -> C
A -> C
总的步数为:7
4
A -> B
A -> C
B -> C
A -> B
C -> A
C -> B
A -> B
A -> C
B -> C
B -> A
C -> A
B -> C
A -> B
A -> C
B -> C
总的步数为:15

附录:四个盘子的移动过程:

这里写图片描述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。 涵盖广泛 精炼的理论讲述搭配大量经典算法示例,学习查询兼而有之。 阐述到位 算法思想、算法实现和完整示例合理搭配,相辅相成。 示例完善 示例分析精准,代码注释精确,每段代码皆可通过编译执行。 计算机技术的发展和普及不仅改变了人们的生活和娱乐方式,也改变了人们的工作方式,这其中最为重要的便是计算机编程技术。现代的设计任务大多通过代码编程交给计算机来完成,其中算法起到了至关重要的作用。可以毫不夸张地说,算法是一切程序设计的灵魂和基础。 《C/C++常用算法手册》分3,共13章,“第1算法基础”介绍了算法概述,重点分析了数据结构和基本算法思想;“第2算法基本应用”详细讲解了算法在排序、查找、数值计算、数论、经典趣题和游戏中的应用;“第3算法高级应用”讲解了算法的一些高级应用技术,包括在密码学和数据压缩/解压缩中的应用。 《C/C++常用算法手册》知识点覆盖全面、结构安排紧凑、讲解详细、示例丰富。《C/C++常用算法手册》对每一个知识点都给出了相应的算法及应用示例。虽然这些例子都是以C语言来编写的,但是算法并不局限于C语言。如果读者采用其他编程语言,例如C++、C#、VB、Java等,根据其语法格式进行适当的修改即可。 《C/C++常用算法手册 》主要定位于有一定C/C++语言编程基础、想通过学习算法与数据结构提升编程水平的读者,也可作为具有一定编程经验的程序员以及大中专院校学生学习数据结构和算法的参考书。 第1 算法基础 1 第1章 算法概述 2 1.1 什么是算法 2 1.2 算法的发展历史 3 1.3 算法的分类 4 1.4 算法相关概念的区别 4 1.5 算法的表示 5 1.5.1 自然语言表示 5 1.5.2 流程图表示 6 1.5.3 N-S图表示 7 1.5.4 伪代码表示 7 1.6 算法的性能评价 8 1.7 算法实例 9 1.7.1 查找数字 9 1.7.2 创建项目 11 1.7.3 编译执行 12 1.8 算法的新进展 13 1.9 小结 14 第2章 数据结构 15 2.1 数据结构概述 15 2.1.1 什么是数据结构 15 2.1.2 数据结构中的基本概念 16 2.1.3 数据结构的内容 16 2.1.4 数据结构的分类 18 2.1.5 数据结构的几种存储方式 18 2.1.6 数据类型 19 2.1.7 常用的数据结构 20 2.1.8 选择合适的数据结构解决实际问题 21 2.2 线性表 21 2.2.1 什么是线性表 21 2.2.2 线性表的基本运算 22 2.3 顺序表结构 23 2.3.1 准备数据 23 2.3.2 初始化顺序表 24 2.3.3 计算顺序表长度 24 2.3.4 插入结点 24 2.3.5 追加结点 25 2.3.6 删除结点 25 2.3.7 查找结点 25 2.3.8 显示所有结点 26 2.3.9 顺序表操作示例 26 2.4 链表结构 30 2.4.1 什么是链表结构 30 2.4.2 准备数据 31 2.4.3 追加结点 31 2.4.4 插入头结点 33 2.4.5 查找结点 33 2.4.6 插入结点 34 2.4.7 删除结点 35 2.4.8 计算链表长度 36 2.4.9 显示所有结点 36 2.4.10 链表操作示例 37 2.5 栈结构 41 2.5.1 什么是栈结构 41 2.5.2 准备数据 42 2.5.3 初始化栈结构 42 2.5.4 判断空栈 43 2.5.5 判断满栈 43 2.5.6 清空栈 43 2.5.7 释放空间 44 2.5.8 入栈 44 2.5.9 出栈 44 2.5.10 读结点数据 45 2.5.11 栈结构操作示例 45 2.6 队列结构 48 2.6.1 什么是队列结构 48 2.6.2 准备数据 49 2.6.3 初始化队列结构 49 2.6.4 判断空队列 50 2.6.5 判断满队列 50 2.6.6 清空队列 50 2.6.7 释放空间 51 2.6.8 入队列 51 2.6.9 出队列 51 2.6.10 读结点数据 52 2.6.11 计算队列长度 52 2.6.12 队列结构操作示例 53 2.7 树结构 56 2.7.1 什么是树结构 56 2.7.2 树的基本概念 56 2.7.3 二叉树 57 2.7.4 准备数据 61 2.7.5 初始化二叉树 61 2.7.6 添加结点 62 2.7.7 查找结点 63 2.7.8 获取左子树 64 2.7.9 获取右子树 64 2.7.10 判断空树 65 2.7.11 计算二叉树深度 65 2.7.12 清空二叉树 65 2.7.13 显示结点数据 66 2.7.14 遍历二叉树 66 2.7.15 树结构操作示例 68 2.8 图结构 71 2.8.1 什么是图结构 71 2.8.2 图的基本概念 72 2.8.3 准备数据 76 2.8.4 创建图 78 2.8.5 清空图 79 2.8.6 显示图 79 2.8.7 遍历图 80 2.8.8 图结构操作示例 81 2.9 小结 84 第3章 基本算法思想 85 3.1 常用算法思想概述 85 3.2 穷举算法思想 85 3.2.1 穷举算法基本思想 86 3.2.2 穷举算法示例 86 3.3 递推算法思想 88 3.3.1 递推算法基本思想 88 3.3.2 递推算法示例 88 3.4 递归算法思想 90 3.4.1 递归算法基本思想 90 3.4.2 递归算法示例 90 3.5 分治算法思想 92 3.5.1 分治算法基本思想 92 3.5.2 分治算法示例 92 3.6 概率算法思想 96 3.6.1 概率算法基本思想 96 3.6.2 概率算法示例 97 3.7 小结 98 第2 算法基本应用 99 第4章 排序算法 100 4.1 排序算法概述 100 4.2 冒泡排序法 101 4.2.1 冒泡排序算法 101 4.2.2 冒泡排序算法示例 102 4.3 选择排序法 104 4.3.1 选择排序算法 104 4.3.2 选择排序算法示例 105 4.4 插入排序法 107 4.4.1 插入排序算法 107 4.4.2 插入排序算法示例 108 4.5 Shell排序法 110 4.5.1 Shell排序算法 110 4.5.2 Shell排序算法示例 111 4.6 快速排序法 113 4.6.1 快速排序算法 113 4.6.2 快速排序算法示例 114 4.7 堆排序法 116 4.7.1 堆排序算法 116 4.7.2 堆排序算法示例 121 4.8 合并排序法 123 4.8.1 合并排序算法 123 4.8.2 合并排序算法示例 126 4.9 排序算法的效率 129 4.10 排序算法的其他应用 130 4.10.1 反序排序 130 4.10.2 字符串数组的排序 132 4.10.3 字符串的排序 135 4.11 小结 137 第5章 查找算法 138 5.1 查找算法概述 138 5.2 顺序查找 138 5.2.1 顺序查找算法 139 5.2.2 顺序查找操作示例 139 5.3 折半查找 141 5.3.1 折半查找算法 141 5.3.2 折半查找操作示例 142 5.4 数据结构中的查找算法 145 5.4.1 顺序表结构中的查找算法 145 5.4.2 链表结构中的查找算法 148 5.4.3 树结构中的查找算法 151 5.4.4 图结构中的查找算法 152 5.5 小结 153 第6章 基本数学问题 154 6.1 判断闰年 154 6.2 多项式计算 156 6.2.1 —维多项式求值 156 6.2.2 二维多项式求值 158 6.2.3 多项式乘法 160 6.2.4 多项式除法 161 6.3 随机数生成算法 164 6.4 复数运算 171 6.4.1 简单的复数运算 172 6.4.2 复数的幂运算 174 6.4.3 复指数运算 176 6.4.4 复对数运算 177 6.4.5 复正弦运算 178 6.4.6 复余弦运算 179 6.5 阶乘 180 6.6 计算π的近似值 183 6.6.1 割圆术 183 6.6.2 蒙特卡罗算法 185 6.6.3 级数公式 187 6.7 矩阵运算 190 6.7.1 矩阵加法 190 6.7.2 矩阵减法 191 6.7.3 矩阵乘法 193 6.8 方程求解 195 6.8.1 线性方程求解——高斯消元法 195 6.8.2 非线性方程求解——二分法 200 6.8.3 非线性方程求解——牛顿迭代法 202 6.9 小结 205 第7章 复杂的数值计算算法 206 7.1 拉格朗日插值 206 7.1.1 拉格朗日插值算法 206 7.1.2 拉格朗日插值示例 207 7.2 数值积分 210 7.2.1 数值积分算法 210 7.2.2 数值积分示例 211 7.3 开平方 213 7.3.1 开平方算法 213 7.3.2 开平方示例 213 7.4 极值问题的求解算法 215 7.4.1 极值求解算法 215 7.4.2 极值求解示例 217 7.5 特殊函数的计算算法 221 7.5.1 伽玛函数 221 7.5.2 贝塔函数 224 7.5.3 正弦积分函数 228 7.5.4 余弦积分函数 231 7.5.5 指数积分函数 235 7.6 小结 239 第8章 经典数据结构问題 240 8.1 动态数组排序 240 8.1.1 动态数组的存储和排序 240 8.1.2 动态数组排序示例 241 8.2 约瑟夫环 243 8.2.1 简单约瑟夫环算法 243 8.2.2 简单约瑟夫环求解 245 8.2.3 复杂约瑟夫环算法 247 8.2.4 复杂约瑟夫环求解 248 8.3 城市之间的最短总距离 250 8.3.1 最短总距离算法 250 8.3.2 最短总距离求解 253 8.4 最短路径 257 8.4.1 最短路径算法 258 8.4.2 最短路径求解 260 8.5 括号匹配 265 8.5.1 括号匹配算法 265 8.5.2 括号匹配求解 267 8.6 小结 270 第9章 数论问题 271 9.1 数论 271 9.1.1 数论概述 271 9.1.2 数论的分类 272 9.1.3 初等数论 273 9.1.4 基本概念 273 9.2 完全数 274 9.2.1 完全数概述 274 9.2.2 计算完全数算法 275 9.3 亲密数 277 9.3.1 亲密数概述 277 9.3.2 计算亲密数算法 277 9.4 水仙花数 280 9.4.1 水仙花数概述 280 9.4.2 计算水仙花数算法 281 9.5 自守数 283 9.5.1 自守数概述 283 9.5.2 计算自守数算法 284 9.6 最大公约数 287 9.6.1 计算最大公约数算法——搌转相除法 287 9.6.2 计算最大公约数算法一一Stein算法 288 9.6.3 计算最大公约数示例 289 9.7 最小公倍数 290 9.8 素数 292 9.8.1 素数概述 292 9.8.2 计算素数算法 292 9.9 回文素数 294 9.9.1 回文素数概述 294 9.9.2 计算回文素数算法 294 9.10 平方回文数 297 9.10.1 平方回文数概述 297 9.10.2 计算平方回文数算法 297 9.11 分解质因数 299 9.12 小结 301 第10 章算法经典趣题 302 0. .l 百钱买百鸡 302 10.1.1 百钱买百鸡算法 302 10.1.2 百钱买百鸡求解 303 10.2 五家共井 304 10.2.1 五家共井算法 304 10.2.2 五家共井求解 305 10.3 鸡兔同笼 307 10.3.1 鸡兔同笼算法 307 10.3.2 鸡兔同笼求解 308 10.4 猴子吃桃 308 10.4.1 猴子吃桃算法 308 10.4.2 猴子吃桃求解 309 10.5 舍罕王赏麦 310 10.5.1 舍罕王赏麦问题 310 10.5.2 舍罕王赏麦求解 311 10.6 汉诺塔 312 10.6.1 汉诺塔算法 312 10.6.2 汉诺塔求解 314 10.7 窃贼问题 315 10.7.1 窃贼问题算法 315 10.7.2 窃贼问题求解 317 10.8 马踏棋盘 320 10.8.1 马踏棋盘算法 320 10.8.2 马踏棋盘求解 321 10.9 八皇后问题 323 10.9.1 八皇后问题算法 324 10.9.2 八皇后问题求解 325 10.10 寻找假银币 327 10.10.1 寻找假银币算法 327 10.10.2 寻找假银币求解 329 10.11 青蛙过河 331 10.11.1 青蛙过河算法 331 10.11.2 青蛙过河求解 333 10.12 三色旗 335 10.12.1 三色旗算法 335 10.12.2 三色旗求解 337 10.13 渔夫捕鱼 339 10.13.1 渔夫捕鱼算法 339 10.13.2 渔夫捕魚求解 340 10.14 爱因斯坦的阶梯 341 10.14.1 爱因斯坦的阶梯算法 341 10.14.2 爱因斯坦的阶梯求解 342 10.15 兔子产仔 342 10.15.1 兔子产仔算法 343 10.15.2 兔子产仔求解 343 10.16 常胜将军 344 10.16.1 常胜将军算法 344 10.16.2 常胜将军求解 345 10.17 新郎和新娘 346 10.17.1 新郎和新娘算法 347 10.17.2 新郎和新娘求解 348 10.18 三色球 349 10.18.1 三色球算法 349 10.18.2 三色球求解 350 10.19 小结 351 第11章 游戏中的算法 352 11.1 洗扑克牌 352 11.1.1 洗扑克牌算法 352 11.1.2 洗扑克牌示例 353 11.2 取火柴游戏 356 11.2.1 取火柴游戏算法 356 11.2.2 取火柴游戏示例 357 11.3 10点半 358 11.3.1 10点半算法 358 11.3.2 10点半游戏示例 363 11.4 生命游戏 368 11.4.1 生命游戏的原理 368 11.4.2 生命游戏的算法 369 11.4.3 生命游戏示例 371 11.5 小结 376 第3 算法高级应用 377 第12章 密码学算法 378 12.1 密码学概述 378 12.1.1 密码学的发展 378 12.1.2 密码学的基本概念 379 12.1.3 柯克霍夫斯原则 379 12.1.4 经典密码学算法 380 12.2 换位加密解密 381 12.2.1 换位加密解密算法 381 12.2.2 换位加密解密算法示例 383 12.3 替换加密解密 386 12.3.1 替换加密解密算法 386 12.3.2 替换加密解密算法示例 388 12.4 位加密解密 389 12.4.1 位加密解密算法 390 12.4.2 位加密解密算法示例 391 12.5 一次一密加密解密算法 392 12.5.1 一次一密加密解密算法 392 12.5.2 一次一密加密解密算法示例 394 12.6 小结 396 第13章 压缩与解压缩算法 397 13.1 压缩与解压缩概述 397 13.1.1 压缩与解压缩分类 397 13.1.2 典型的压缩解压缩算法 397 13.2 压缩算法 398 13.3 解压缩算法 401 13.4 压缩/解压缩示例 404 13.5 小结 406

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值