深度优先遍历与广度优先遍历(c++二叉树算法实现)

图的遍历算法详解
本文详细介绍了图的两种主要遍历算法:深度优先遍历和广度优先遍历。深度优先遍历采用递归或栈的方式进行实现,尽可能深地搜索图的分支。广度优先遍历则通过队列来实现,按层次顺序访问顶点。

1.深度优先遍历的递归定义

  假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

  图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索(Depth-First Search)。相应地,用此方法遍历图就很自然地称之为图的深度优先遍历

 

2.基本实现思想:

(1)访问顶点v;

(2)从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;

(3)重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

 

3.伪代码

递归实现

1)访问顶点v;visited[v]=1;//算法执行前visited[n]=0

(2)w=顶点v的第一个邻接点;

(3)while(w存在)  

           if(w未被访问)

                   从顶点w出发递归执行该算法; 
           w=顶点v的下一个邻接点;

 

非递归实现

 (1)栈S初始化;visited[n]=0;

 (2)访问顶点v;visited[v]=1;顶点v入栈S

 (3)while(栈S非空)

            x=栈S的顶元素(不出栈);

            if(存在并找到未被访问的x的邻接点w)

                    访问w;visited[w]=1;

                    w进栈;

            else

                     x出栈;

 广度优先遍历

1.广度优先遍历定义

 图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。 

2.基本实现思想

(1)顶点v入队列。

(2)当队列非空时则继续执行,否则算法结束。

(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。

(4)查找顶点v的第一个邻接顶点col。

(5)若v的邻接顶点col未被访问过的,则col入队列。

(6)继续查找顶点v的另一个新的邻接顶点col,转到步骤(5)。

        直到顶点v的所有未被访问过的邻接点处理完。转到步骤(2)。

广度优先遍历图是以顶点v为起始点,由近至远,依次访问和v有路径相通而且路径长度为1,2,……的顶点。为了使“先被访问顶点的邻接点”先于“后被访问顶点的邻接点”被访问,需设置队列存储访问的顶点。

3.伪代码

(1)初始化队列Q;visited[n]=0;

(2)访问顶点v;visited[v]=1;顶点v入队列Q;

(3) while(队列Q非空)   

              v=队列Q的对头元素出队;

              w=顶点v的第一个邻接点;

             while(w存在) 

                     如果w未访问,则访问顶点w;

                     visited[w]=1;

                     顶点w入队列Q;

                     w=顶点v的下一个邻接点。

转自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/18/2596983.html

递归深度优先遍历:分为先序、中序、后序遍历

  1. //前序遍历  
  2. void PreOrderTraverse(BiTree T)  
  3. {  
  4.     if(T){  
  5.         printf("%c ",T->ch);  
  6.         PreOrderTraverse(T->lchild);  
  7.         PreOrderTraverse(T->rchild);  
  8.     }  
  9. }  
  10.   
  11. //中序遍历  
  12. void InOrderTraverse(BiTree T)  
  13. {  
  14.     if(T){  
  15.         InOrderTraverse(T->lchild);  
  16.         printf("%c ",T->ch);  
  17.         InOrderTraverse(T->rchild);  
  18.     }  
  19. }  
  20.   
  21. //后序遍历  
  22. void PostOrderTraverse(BiTree T)  
  23. {  
  24.     if(T){  
  25.         PostOrderTraverse(T->lchild);  
  26.         PostOrderTraverse(T->rchild);  
  27.         printf("%c ",T->ch);  
  28.     }  
  29. }

非递归深度优先遍历:是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。先序遍历如下所示,中序和后序同理~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//深度优先遍历二叉树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);  //再将左子树压栈
        }
    }
}
</node>

 

广度优先遍历:是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//广度优先遍历
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);  //再将右子树入队
        }
    }
}
</node>
转自:http://www.cnblogs.com/calamus/p/5877758.html
<think> 首先,用户的问题是:“我想了解在C++中对树结构进行深度优先遍历广度优先遍历的相关知识 请问C++实现树结构的深度优先遍历广度优先遍历”。这意味着我需要解释深度优先遍历(DFS)广度优先遍历(BFS)在树结构中的概念,并提供C++代码实现。 从系统级指令中,我需要: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 我需要参考提供的引用: - 引用[1]:二叉树深度优先遍历广度优先遍历C++实现。 - 引用[2]:二叉搜索树的深度广度优先遍历C++实现。 - 引用[3]:多叉树的深度优先遍历DFS广度优先遍历BFS的C++递归非递归方式实现。 - 引用[4]:树的广度优先遍历深度优先遍历算法,包括队列的使用。 用户指定了树结构,所以我应该考虑一般树或二叉树。引用中提到二叉树多叉树,所以我需要覆盖这些。为了通用性,我可以从二叉树开始,然后扩展到多叉树。 回答结构: 1. 解释深度优先遍历(DFS)广度优先遍历(BFS)的概念。 2. 提供C++代码实现:包括递归非递归版本。 3. 使用清晰的结构:分步骤解释。 4. 在结尾添加相关问题。 5. 添加引用标识,基于提供的引用。 概念解释: - BFS:从根节点开始,按层次遍历,使用队列。 - DFS:深入遍历每个分支,使用栈(递归或非递归)。DFS有前序、中序、后序等变体。 对于树结构,我将以二叉树为例,因为它是基础。然后提到扩展到多叉树。 C++实现: - BFS:使用队列。 - DFS:递归非递归版本。 - 需要定义树节点结构。 定义树节点: ```cpp struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; ``` 对于多叉树: ```cpp struct MultiTreeNode { int val; std::vector<MultiTreeNode*> children; MultiTreeNode(int x) : val(x) {} }; ``` 但在回答中,我主要使用二叉树,并提到多叉树。 步骤: 1. 引入主题。 2. 解释DFSBFS。 3. 提供代码示例。 4. 讨论递归非递归。 5. 添加相关问题。 引用标识:我需要自然地添加。例如,在解释概念时引用[^4],在代码时引用[^1]或[^2]。 生成相关问题: 在结尾添加§§相关问题§§部分。 完整结构: - 开头:简要介绍树遍历。 - 解释BFS:概念C++实现。 - 解释DFS:概念C++实现(递归非递归)。 - 结尾:相关问题。 使用中文回答。 </think> ### 树结构的深度优先遍历广度优先遍历C++实现) 在树结构中,深度优先遍历(DFS)广度优先遍历(BFS)是两种基本遍历方法。DFS 优先深入访问每个分支,适合路径搜索或回溯问题;BFS 则按层次遍历,适合最短路径或层级分析。树可以是二叉树或多叉树,本文以二叉树为例(可扩展到多叉树),并提供 C++ 递归非递归实现。树节点定义如下: ```cpp #include <iostream> #include <queue> #include <stack> #include <vector> // 二叉树节点结构 struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; ``` #### 1. 广度优先遍历(BFS) BFS 从根节点开始,逐层访问节点(从左到右)。它使用队列(先进先出)存储待访问节点,确保按层次遍历算法复杂度为 $O(n)$,其中 $n$ 是节点总数。树的广度优先遍历算法通过队列实现,先访问根节点,再按顺序处理子节点[^4]。 **C++ 实现(非递归,使用队列)**: ```cpp void bfs(TreeNode* root) { if (!root) return; std::queue<TreeNode*> q; q.push(root); while (!q.empty()) { TreeNode* current = q.front(); q.pop(); std::cout << current->val << " "; // 输出节点值,可根据需求修改 // 将子节点加入队列 if (current->left) q.push(current->left); if (current->right) q.push(current->right); } } ``` **示例说明**: - 输入树:根节点值为 1,左节点值为 2,右节点值为 3。 - 遍历顺序:1 → 2 → 3。 - 队列操作:初始队列 [1] → 取 1,加入子节点 → 队列 [2, 3] → 取 2,加入子节点(假设无子节点)→ 队列 [3] → 取 3。 #### 2. 深度优先遍历(DFS) DFS 优先访问节点的最深子节点,常见变体包括前序(根-左-右)、中序(左-根-右)后序(左-右-根)。算法复杂度为 $O(n)$。DFS 可通过递归(隐式栈)或非递归(显式栈)实现。树的深度优先遍历方法类似于图遍历,适用于树结构的高效搜索[^2]。 **DFS 实现方式**: - **前序遍历(递归)**: ```cpp void dfs_preorder_recursive(TreeNode* root) { if (!root) return; std::cout << root->val << " "; // 访问根节点 dfs_preorder_recursive(root->left); // 递归左子树 dfs_preorder_recursive(root->right); // 递归右子树 } ``` - **前序遍历(非递归,使用栈)**: ```cpp void dfs_preorder_iterative(TreeNode* root) { if (!root) return; std::stack<TreeNode*> s; s.push(root); while (!s.empty()) { TreeNode* current = s.top(); s.pop(); std::cout << current->val << " "; // 栈先进后出,先右后左 if (current->right) s.push(current->right); if (current->left) s.push(current->left); } } ``` - **中序遍历(递归)**: ```cpp void dfs_inorder_recursive(TreeNode* root) { if (!root) return; dfs_inorder_recursive(root->left); // 递归左子树 std::cout << root->val << " "; // 访问根节点 dfs_inorder_recursive(root->right); // 递归右子树 } ``` - **中序遍历(非递归)**: ```cpp void dfs_inorder_iterative(TreeNode* root) { std::stack<TreeNode*> s; TreeNode* current = root; while (current || !s.empty()) { while (current) { // 遍历到最左节点 s.push(current); current = current->left; } current = s.top(); s.pop(); std::cout << current->val << " "; current = current->right; // 处理右子树 } } ``` - **后序遍历(递归)**: ```cpp void dfs_postorder_recursive(TreeNode* root) { if (!root) return; dfs_postorder_recursive(root->left); // 递归左子树 dfs_postorder_recursive(root->right); // 递归右子树 std::cout << root->val << " "; // 访问根节点 } ``` - **后序遍历(非递归)**: ```cpp void dfs_postorder_iterative(TreeNode* root) { if (!root) return; std::stack<TreeNode*> s1, s2; s1.push(root); while (!s1.empty()) { TreeNode* current = s1.top(); s1.pop(); s2.push(current); // 用于反转顺序 if (current->left) s1.push(current->left); if (current->right) s1.push(current->right); } while (!s2.empty()) { std::cout << s2.top()->val << " "; s2.pop(); } } ``` **示例说明**(以二叉树为例): - 输入树:根节点值为 1,左节点值为 2(有子节点 4),右节点值为 3。 - 前序遍历:1 → 2 → 4 → 3。 - 中序遍历:4 → 2 → 1 → 3。 - 后序遍历:4 → 2 → 3 → 1。 #### 扩展到多叉树 多叉树节点定义: ```cpp struct MultiTreeNode { int val; std::vector<MultiTreeNode*> children; MultiTreeNode(int x) : val(x) {} }; ``` - **BFS 实现**:类似二叉树,队列处理所有子节点。 - **DFS 实现**:递归遍历每个子节点,例如前序遍历: ```cpp void dfs_multi_preorder(MultiTreeNode* root) { if (!root) return; std::cout << root->val << " "; for (auto child : root->children) { dfs_multi_preorder(child); } } ``` #### 性能应用 - **BFS**:空间复杂度 $O(w)$,其中 $w$ 是树的最大宽度,适合内存受限场景[^4]。 - **DFS**:递归空间复杂度 $O(h)$($h$ 为树高),非递归空间复杂度 $O(h)$,适合深度搜索[^3]。 - **应用场景**:BFS 用于层级打印或最短路径(如文件系统遍历),DFS 用于表达式树求值或序列化[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值