递归与搜索算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第2章 线性表
队列
先进先出(first in/first out, FIFO)线性结构。
队首:删除端 队尾:插入端
排队 买票
第2章 线性表
队列操作
Clear()— 清空队列。 IsEmpty()— 判断队列是否为空。 IsFull() — 判断队列是否已满 EnQueue(T item)— 队列的尾部加入元素item。 DeQueue(T& item)— 取出队列的第一个元素。 GetFront(T& item)— 返回队列的第一个元素,但不移去它。
int u=v; Queue q(size)// q is a queue of unexplored vertices. visited[v]=1; do{ For all vertices w adjacent from u{ If(visited[w]==0){ q . add(w);// w is unexplored. Visited[w]=1; } } } If(q.qempty()) return;// No unexplored vertex. }while(1);
伪代码
Void DFS (int V) //Given an graph G(V,E) with n vertices and an array visited[] initially //set to zero , this algorithm visits all vertices reachable from v .G and visited[] // are global.
{
visited[v]=1; for each vertex w adjacent from V{ if(!visited[w]) DFS(w); } }
下面是一棵搜索树
1
2
3
4
5
6
7
8
9
10
对图的深度优先遍历
图的深度优先搜索中,我们从定点v开始,标记
它为已经到达(已访问)。这时,顶点v称为未 考察的点。当已经访问过某个顶点的所有相邻定 点后,在算法中这个顶点称为已经考察的顶点。 图的深度优先搜索是指,只要到达一个新的定顶 点,顶点v的考查就暂停,新的顶点u的考查开始。 当这个新的顶点考察结束后,继续顶点v的考查。 当所有可达定点被全部考察结束后,搜索停止。
total(n–m,m) + total(n,m-1)
介绍几种数据结构

栈:限定仅只能在末端进行插入和删除的线性表。
栈顶:允许插入和删除的一端。
栈底:不允许插入和删除的一端。 时间有序表:先进后出(FILO) /后进先出(LIFO)
退栈
进栈
(压入) an-1 an-2 … a1 a0
(弹出)
top
第2章 线性表
树的基本术语
结点:包含一个数据元素及若干指向其子树的分支。
结点的度:结点拥有的子树个数。
A B E K L F H M D I
树的基本术语
路径与路径长度:路径的长度等于路径所通过的结 点数目减1(即路径上分支数目)。 子女结点、父母结点、祖先、后继
A B E K L F H M D I
图的定义和基本术语
图 G 是由两个集合顶点集 V(G) 和边集 E(G) 组成的,记 作G=( V(G),E(G) ),简称G=(V,E)。 V(vertex)是顶点的有穷非空集合 E(edge)是两个顶点之间的关系,即边的有穷集合 A A C C B B
D D
E E
深度优先搜索
递归
递归的定义
深度优先搜索
}
广度优先搜索
递归
递归的定义
深度优先搜索
深度搜索定义 深搜过程 在深度优先搜索算法中,是深度越大的结点越先得到扩展。 递归的特点
广度优先搜 索
如果在搜索中把算法改为按结点的层次进行搜索, 本层的 结点没有搜索处理完时,不能对下层结点进行处理,即深度 越小的结点越先得到扩展。
也就是说先产生的结点先得以扩展处理,这种搜索算法称为 广度优先搜索法。
递归思想和搜索算法
数模组 费鹏
递归
递归定义 在调用一个函数的过程中又出现直接或间接地调用该函数 本身,成为函数的递归调用。
递归思想和搜索算法
递归
例如:
递归的定义 递归的特点 深度搜索定义 深搜过程
深度优先搜索
广度优先搜 索
int fun(int n){ int t; if(n == 1) t = 1; else t = n * fun(n - 1); return t;
深度搜索定义 深搜过程
广度优先搜 索
递归的特点 深度优先搜索就是在搜索树的每一层始终先只扩展一个子节 点,不断地向纵深前进。
当不能再前进(到达叶子节点或受到深度限制)时,才从当 前节点返回到上一级节点,沿另一方向又继续前进。 这种方法的搜索树是从树根开始一枝一枝逐渐形成的。
伪代码
Void DFS (int V) //Given an graph G(V,E) with n vertices and an array visited[] initially //set to zero , this algorithm visits all vertices reachable from v .G and // visited[] are global.
考虑一个新问题: 现在有n个苹果和m个盘子,把这些苹果都放到盘子里,可以有盘 子里一个苹果也不放,有多少种摆放方法。
关注最后一个条件,即可能存在也可能不存在没放苹果的盘 子。 结果可为以下两种情况的和 有空盘子的情况,则问题可简化为n个苹果放m – 1个盘子。 没有空盘子的情况,则问题可简化为n – m个苹果放m个盘 子 可以得到递归公式,total总数 1, total(n, m) total(n, n), n = 0 or m = 1 n < m
对图的广度优先遍历
B E
H
A
D
G
C百度文库
F
I
上图的搜索树 A B C D
E
F
H
I
G
如何实现广度优先搜索? 一种数据结构可以帮助实现 --队列 队列可以简化为一种退化了的数组 仅支持总头部提取元素和从尾部添加元素 类比生活中的队伍 先到的人排在队首,先接受服务,后到的人排在队尾, 最后接受服务。
再来一次
Void BFS (int V)
伪代码
//A breadth first search of G is carried out beginning
//at vertex v. For any node i , visited[i]==1 if i has already been visited. The //graph G and array visited[] are global; visited[] is initialized to zero. {
{
visited[v]=1; for each vertex w adjacent from V{ if(!visited[w]) DFS(w); } }
实际应用:
八皇后问题 描述:在8X8格的国际象棋上摆放八个皇后,使其不能互相 攻击,即任意两个皇后都不能处于同一行、同一列或同一斜 线上,问有多少种摆法。
int u=v; Queue q(size)// q is a queue of unexplored vertices. visited[v]=1; do{ For all vertices w adjacent from u{ If(visited[w]==0){ q . add(w);// w is unexplored. Visited[w]=1; } } } If(q.qempty()) return;// No unexplored vertex. }while(1);
一个四皇后的解
如何实现:
树状结构 每一行为一个搜索层,一共有8层 每一列为一个生成节点,也就是一层有8个节点 符合要求且能搜索到第8层的就是一个解。 8 * 8棋盘有92个解
int map[8];//记录棋子的位置 void DFS(int l){ int i, j; if(l >= 8){//搜索到第8层以上时得到一个解 for(i = 0;i < 8;i ++) printf("%d", map[i]); printf("\n"); } for(i = 1;i <= 8;i ++)//对每一个可行子节点进行深搜 { for(j = 0;j < l;j ++)//判断是否可行 { if(map[j] == i || map[j] + j == l + i || map[j] - j == i - l) break; } if(j >= l) { map[l] = i;//记录棋子的位置 DFS(l + 1); map[l] = 0;//返回上一层时要清空这层的信息 } } }
}
下面是一棵搜索树
1
2
3
4
5
6
7
8
9
10
图的广度优先算法

在广度优先算法中,我们从定点v开始,标记它为已经到 达(已访问)。这时,顶点v称为未考察的点。当已经访 问过某个顶点的所有相邻定点后,在算法中这个顶点称 为已经考察的顶点。接着访问v的所有相邻的未访问的顶 点,这些是新的未考察的顶点,顶点v现在成为已考察的 顶点。最新访问的顶点还未考察,放置在队列的尾部, 队列的首结点就是下一个要考察的点。当不存在为考察 的点时,考察停止。
bottom
第2章 线性表
栈的基本操作
● Clear()——清空栈。 ● IsEmpty()——判断栈是否为空。 ● Push(T item)——将元素item放到栈的顶部。 ● Pop(T& item)——取出栈顶部的元素。 ● Top (T& item)——获取栈顶部的元素,但不删除该元素。 ● IsFull()——判断栈是否已满
n=2 t=2*fun(1)
考虑若在return语句前加入printf(“%d”, t),会有怎 么的输出结果
为什么能用递归解决这个问题?
阶乘问题可以分解为规模更小的子问题,用同样的方法可以解子问题
可以很容易的得到关于阶乘问题的递归公式: 1, n = 0, 1
n! =
n * (n - 1)!, n > 1
Visited[]哪 去了???
考虑一个新问题:
在n*m的棋盘上有一只 马,它能像图示那样走 现在它想遍历每一个棋 格,它该怎么做?
Bool DFS(int i , int j) {
step++; route[step]=(i,j) //position visited[i][j]=true; if(step==n*m) return true; for(int n=1;n<9;n++){ path(i,j,n); //How will the rider move //x,y is the point that has been moved if(!map[x][y]&&x>=1&&x<=m&&y>='A'&&y<=n+'A'-1) if(DFS(x,y)) return true; } map[i][j]=false; step--; return false;
1
2
3
4
5
6
7 1 2 3 4
8 5 6 7
9 8 9
10 10
伪代码
Void BFS (int V)
//A breadth first search of G is carried out beginning
//at vertex v. For any node i , visited[i]==1 if i has already been visited. The //graph G and array visited[] are global; visited[] is initialized to zero. {
}
考虑一下刚才那个函数的运行过程
以起始n为5为例 有fun(5)调用fun(4),fun(4)调用fun(3)„,直到n = 1为止 然后依次向上一层返回值。 n=5 t=5*fun(4)
输出120 输出24
n=3 t=3*fun(2)
输出6 输出2
n=1 t=1
输出1
n=4 t=4*fun(3)
对图的深度优先遍历
B E
H
A
D
G
C
F
I
上图的搜索树 A B C
E
D
H
F
I
G
如何实现深度优先搜索
递归可以很方便地解决 对某个一个节点的深度优先搜索可以简化为对它的所有子节 点进行深度优先搜索
对于节点1来说,它能产生2和3两个节点,分别对2和3进 行深搜其实就完成了对1的深搜,而对2和3的搜索又可以 进一步划分。
相关文档
最新文档