轉自:http://www.blogjava.net/fancydeepin/archive/2013/02/03/395073.htmlhtml
深度優先搜索算法(Depth First Search),是搜索算法的一種。是沿着樹的深度遍歷樹的節點,儘量深的搜索樹的分支。
當節點v的全部邊都己被探尋過,搜索將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的全部節點爲止。
若是還存在未被發現的節點,則選擇其中一個做爲源節點並重復以上過程,整個進程反覆進行直到全部節點都被訪問爲止。java
如右圖所示的二叉樹:
A 是第一個訪問的,而後順序是 B、D,而後是 E。接着再是 C、F、G。
那麼,怎麼樣才能來保證這個訪問的順序呢?
分析一下,在遍歷了根結點後,就開始遍歷左子樹,最後纔是右子樹。
所以能夠藉助堆棧的數據結構,因爲堆棧是後進先出的順序,由此能夠先將右子樹壓棧,而後再對左子樹壓棧,
這樣一來,左子樹結點就存在了棧頂上,所以某結點的左子樹能在它的右子樹遍歷以前被遍歷。
深度優先遍歷代碼片斷node
//
深度優先遍歷
void
depthFirstSearch(Tree root){
stack
<
Node
*>
nodeStack;
//
使用C++的STL標準模板庫
nodeStack.push(root);
Node
*
node;
while
(
!
nodeStack.empty()){
node
=
nodeStack.top();
printf(format, node
->
data);
//
遍歷根結點
nodeStack.pop();
if
(node
->
rchild){
nodeStack.push(node
->
rchild);
//
先將右子樹壓棧
}
if
(node
->
lchild){
nodeStack.push(node
->
lchild);
//
再將左子樹壓棧
}
}
}
廣度優先搜索算法(Breadth First Search),又叫寬度優先搜索,或橫向優先搜索。
是從根節點開始,沿着樹的寬度遍歷樹的節點。若是全部節點均被訪問,則算法停止。
如右圖所示的二叉樹,A 是第一個訪問的,而後順序是 B、C,而後再是 D、E、F、G。
那麼,怎樣才能來保證這個訪問的順序呢?
藉助隊列數據結構,因爲隊列是先進先出的順序,所以能夠先將左子樹入隊,而後再將右子樹入隊。
這樣一來,左子樹結點就存在隊頭,能夠先被訪問到。
廣度優先遍歷代碼片斷web
//
廣度優先遍歷
void
breadthFirstSearch(Tree root){
queue
<
Node
*>
nodeQueue;
//
使用C++的STL標準模板庫
nodeQueue.push(root);
Node
*
node;
while
(
!
nodeQueue.empty()){
node
=
nodeQueue.front();
nodeQueue.pop();
printf(format, node
->
data);
if
(node
->
lchild){
nodeQueue.push(node
->
lchild);
//
先將左子樹入隊
}
if
(node
->
rchild){
nodeQueue.push(node
->
rchild);
//
再將右子樹入隊
}
}
}
完整代碼:算法
/*
*
* <!--
* File : binarytree.h
* Author : fancy
* Email : fancydeepin@yeah.net
* Date : 2013-02-03
* --!>
*/
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
<
malloc.h
>
#include
<
Stack
>
#include
<
Queue
>
using
namespace
std;
#define
Element char
#define
format "%c"
typedef
struct
Node {
Element data;
struct
Node
*
lchild;
struct
Node
*
rchild;
}
*
Tree;
int
index
=
0
;
//
全局索引變量
//
二叉樹構造器,按先序遍歷順序構造二叉樹
//
無左子樹或右子樹用'#'表示
void
treeNodeConstructor(Tree
&
root, Element data[]){
Element e
=
data[index
++
];
if
(e
==
'
#
'
){
root
=
NULL;
}
else
{
root
=
(Node
*
)malloc(
sizeof
(Node));
root
->
data
=
e;
treeNodeConstructor(root
->
lchild, data);
//
遞歸構建左子樹
treeNodeConstructor(root
->
rchild, data);
//
遞歸構建右子樹
}
}
//
深度優先遍歷
void
depthFirstSearch(Tree root){
stack
<
Node
*>
nodeStack;
//
使用C++的STL標準模板庫
nodeStack.push(root);
Node
*
node;
while
(
!
nodeStack.empty()){
node
=
nodeStack.top();
printf(format, node
->
data);
//
遍歷根結點
nodeStack.pop();
if
(node
->
rchild){
nodeStack.push(node
->
rchild);
//
先將右子樹壓棧
}
if
(node
->
lchild){
nodeStack.push(node
->
lchild);
//
再將左子樹壓棧
}
}
}
//
廣度優先遍歷
void
breadthFirstSearch(Tree root){
queue
<
Node
*>
nodeQueue;
//
使用C++的STL標準模板庫
nodeQueue.push(root);
Node
*
node;
while
(
!
nodeQueue.empty()){
node
=
nodeQueue.front();
nodeQueue.pop();
printf(format, node
->
data);
if
(node
->
lchild){
nodeQueue.push(node
->
lchild);
//
先將左子樹入隊
}
if
(node
->
rchild){
nodeQueue.push(node
->
rchild);
//
再將右子樹入隊
}
}
}
二叉樹的深度優先遍歷(中序遍歷):數據結構
當咱們利用樹的深度優先遍歷找到知足條件的一條路徑時,須要設置一個bool類型標誌,若是在左子樹中已經找到,則不需遞歸右子樹,通常採用如下步驟:spa
Bool findPath(pCur,pNode).net
If(知足條件)orm
Return true;htm
s.push(pcur);
Bool found=false;//設置一個標誌,來判斷是否已經找到了一條路徑
If(pCur->left)
found=findPath(pCur->left,pNode);
If(pCur->right && !found) //找到了就不用遞歸
found=findPath(pCur->right,pNode);
If(!found)
s.pop();
Return found;
當咱們須要找到全部知足條件的路徑時,通常採用以下步驟:
Void findPath(pcur,pnode)
If(知足條件)
Print;
更新狀態;
s.push(pcur);
If(pcur->left)
Findpath(pcur->left,pnode);
If(pcur->right)
Findpath(pcur->right,pnode);
還原添加此節點時的狀態;
s.pop();