图/树——深度优先搜索(DFS)

转载

深度优先搜索(DFS, Depth First Search)是一个针对图和树的遍历算法。早在19世纪就被用于解决迷宫问题。

对于下面的树而言,DFS方法首先从根节点1开始,其搜索节点顺序是1,2,3,4,5,6,7,8(假定左分枝和右分枝中优先选择左分枝)。 
这里写图片描述
DFS的实现方式相比于BFS应该说大同小异,只是把queue换成了stack而已,stack具有后进先出LIFO(Last Input First Output)的特性,DFS的操作步骤如下: 
1、把起始点放入stack; 
2、重复下述3步骤,直到stack为空为止:

  • 从stack中访问栈顶的点;
  • 找出与此点邻接的且尚未遍历的点,进行标记,然后全部放入stack中;
  • 如果此点没有尚未遍历的邻接点,则将此点从stack中弹出。

下面结合一个图(graph)的实例,说明DFS的工作过程和原理: 
(1)将起始节点1放入栈stack中,标记为已遍历。 
这里写图片描述
(2)从stack中访问栈顶的节点1,找出与节点1邻接的节点,有2,8两个节点,我们可以选择其中任何一个,选择规则可以人为设定,这里假设按照节点数字顺序由小到大选择,选中的是2,标记为已遍历,然后放入stack中。 
这里写图片描述
(3)从stack中取出栈顶的节点2,找出与节点2邻接的节点,有1,3,5三个节点,节点1已遍历过,排除;3,5中按照预定的规则选中的是3,标记为已遍历,然后放入stack中。 
这里写图片描述
(4)从stack中取出栈顶的节点3,找出与节点3邻接的节点,有2,4两个节点,节点2已遍历过,排除;选中的是节点4,标记为已遍历,然后放入stack中。 
这里写图片描述
(5)从stack中取出栈顶的节点4,找出与节点4邻接的节点,有3,5,6三个节点,节点3已遍历过,排除;选中的是节点5,标记为已遍历,然后放入stack中。 
这里写图片描述
(6)从stack中取出栈顶的节点5,找出与节点5邻接的节点,有2,4两个节点,节点2,4都已遍历过,因此节点5没有尚未遍历的邻接点,则将此点从stack中弹出。 
这里写图片描述
(7)当前stack栈顶的节点是4,找出与节点4邻接的节点,有3,5,6三个节点,节点3,5都已遍历过,排除;选中的是节点6,标记为已遍历,然后放入stack中。 
这里写图片描述
(8)当前stack栈顶的节点是6,找出与节点6邻接的节点,有4,7,8三个节点,4已遍历,按照规则选中的是7,标记为已遍历,然后放入stack中。 
这里写图片描述
(9)当前stack栈顶的节点是7,找出与节点7邻接的节点,只有节点6,已遍历过,因此没有尚未遍历的邻接点,将节点7从stack中弹出。 
这里写图片描述
(10)当前stack栈顶的节点是6,找出与节点6邻接的节点,有节点7,8,7已遍历过,因此将节点8放入stack中。 
这里写图片描述
(11)当前stack栈顶的节点是8,找出与节点8邻接的节点,有节点1,6,9,1,6已遍历过,因此将节点9放入stack中。 
这里写图片描述
(12)当前stack栈顶的节点是9,没有尚未遍历的邻接点,将节点9弹出,依次类推,栈中剩余节点8,6,4,3,2,1都没有尚未遍历的邻接点,都将弹出,最后栈为空。 
(13)DFS遍历完成。

 

在二叉树中DFS遍历代码(仅考虑了前序遍历,中后序也可以实现):

// DFS的递归实现
void DFS_Recursive(Node* pRoot)
{
	if (pRoot==NULL)
		return;
 
	cout<<pRoot->nVal<<" ";
 
	if (pRoot->pLeft!=NULL)	
		DFS_Recursive(pRoot->pLeft);
 
 
	if (pRoot->pRight!=NULL)
		DFS_Recursive(pRoot->pRight);
	
}
 
// DFS的迭代实现版本(stack)
void DFS_Iterative(Node* pRoot)
{
	if (pRoot==NULL)
		return;
 
	stack<Node*> S;
	S.push(pRoot);
 
	while (!S.empty())
	{
		Node *node=S.top();
		cout<<node->nVal<<",";
 
		S.pop();
 
		if (node->pRight!=NULL) //注意进栈方式--先右后左
		{
			S.push(node->pRight);
		}
 
		if (node->pLeft!=NULL)
		{
			S.push(node->pLeft);
		}
		
	}
 
}

 

  • 14
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值