演示了如何使用C++和STL模板库实现深度优先遍历(DFS)和广度优先遍历(BFS)的算法。

此代码用C++智能指针实现

深度优先遍历(DFS)是一种重要的图遍历算法,它在许多问题中都有着重要的应用。以下是一些使用深度优先遍历的常见情况:

图的连通性检测:DFS 可以用于检测图中的连通分量,以及判断图是否连通。
寻找路径:DFS 可以用于寻找从一个节点到另一个节点的路径,例如在迷宫问题、图的最短路径问题中。
拓扑排序:DFS 可以用于拓扑排序,对有向无环图(DAG)进行排序。
生成树:DFS 可以用于生成树,例如在生成迷宫的过程中。
回溯算法:DFS 是回溯算法的基础,在解决组合优化、搜索解空间等问题时非常有用。
DFS 的一个重要特点是它能够快速地到达图的最深处,因此适用于需要沿着一条路径尽可能深入地探索的情况。

广度优先遍历(BFS)同样是一种重要的图遍历算法,在许多情况下都有着重要的应用。以下是一些使用广度优先遍历的常见情况:

最短路径搜索:在无权图中,广度优先遍历可以用于寻找从一个节点到另一个节点的最短路径。
最小生成树:BFS 可以用于生成图的最小生成树,例如 Prim 算法的实现。
寻找连通分量:BFS 可以用于确定无向图的连通分量,以及判断图是否连通。
拓扑排序:在有向无环图(DAG)中,BFS 可以用于拓扑排序,即将图中的节点排序为线性序列。
网络流:BFS 可以用于寻找网络流中的增广路径,例如在 Ford-Fulkerson 算法中。
解决状态空间搜索问题:例如在迷宫问题中,广度优先搜索可以用于寻找从起点到终点的最短路径。
广度优先遍历的一个重要特点是它从起始节点开始,逐层地向外扩展,因此适用于需要逐层探索的情况,特别是在寻找最短路径或最优解的问题中。

深度优先遍历中的优先序、中序和后序指的是节点的访问顺序,它们在遍历树或图时访问节点的顺序不同,各自有其特定的应用场景和优势:

先序遍历(Preorder)

根节点首先被访问,然后依次访问左子树和右子树。
适用于树的复制和序列化,以及构建表达式树等情况。
适用于查找树中某个特定的值,或者对树进行排序。

中序遍历(Inorder)

先访问左子树,然后访问根节点,最后访问右子树。
对于二叉搜索树(BST)而言,中序遍历可以按照节点的值从小到大的顺序访问节点。
适用于查找树中某个特定的值,或者对树进行排序。

后序遍历(Postorder)

先访问左子树,然后访问右子树,最后访问根节点。
适用于进行内存管理、释放资源等操作,也可用于求表达式树的值。
每种遍历顺序都有其独特的应用场景,选择合适的遍历方式取决于具体的问题需求。

用递归实现实现了深度优先遍历的先序、中序和后序遍历

其中,树节点类TreeNode是一个模板类,用于存储树节点的数据和指向左右子节点的指针。
深度优先遍历类Dfs包含了静态方法preorder、inorder和postorder,分别用于实现先序、中序和后序遍历。
使用智能指针std::shared_ptr来管理树节点的内存。
在main函数中,构建了一棵二叉树,然后依次进行先序、中序和后序遍历,并输出遍历结果。
#include <iostream>
#include <memory>

// 定义树节点类模板
template<typename T>//定义泛型T
class TreeNode {
public:
    T data; // 节点数据
    std::shared_ptr<TreeNode<T>> left; // 左子节点指针
    std::shared_ptr<TreeNode<T>> right; // 右子节点指针

    // 构造函数,初始化节点数据和指针
    TreeNode(T data, std::shared_ptr<TreeNode<T>> left = nullptr, std::shared_ptr<TreeNode<T>> right = nullptr)
        : data(data), left(left), right(right) {}
};

// 定义深度优先遍历类
class Dfs {
public:
    // 先序遍历
    template<typename T>
    static void preorder(std::shared_ptr<TreeNode<T>> treeNode) {
        if (treeNode == nullptr) {
            return;
        }

        process(treeNode);  // 处理根节点
        preorder(treeNode->left); // 遍历左子树
        preorder(treeNode->right); // 遍历右子树
    }

    // 中序遍历
    template<typename T>
    static void inorder(std::shared_ptr<TreeNode<T>> treeNode) {
        if (treeNode == nullptr) {
            return;
        }

        inorder(treeNode->left); // 遍历左子树
        process(treeNode);  // 处理根节点
        inorder(treeNode->right); // 遍历右子树
    }

    // 后序遍历
    template<typename T>
    static void postorder(std::shared_ptr<TreeNode<T>> treeNode) {
        if (treeNode == nullptr) {
            return;
        }

        postorder(treeNode->left); // 遍历左子树
        postorder(treeNode->right); // 遍历右子树
        process(treeNode);  // 处理根节点
    }

private:
    // 静态方法,处理节点
    template<typename T>
    static void process(std::shared_ptr<TreeNode<T>> node) {
        std::cout << "Value = " << node->data << std::endl; // 输出节点数据
    }
};

int main() {
    // 构建树节点
    auto root = std::make_shared<TreeNode<int>>(1);
    root->left = std::make_shared<TreeNode<int>>(2);
    root->right = std::make_shared<TreeNode<int>>(3);
    root->left->left = std::make_shared<TreeNode<int>>(4);
    root->left->right = std::make_shared<TreeNode<int>>(5);
    root->right->left = std::make_shared<TreeNode<int>>(6);
    root->right->right = std::make_shared<TreeNode<int>>(7);

    // 先序遍历
    std::cout << "Preorder traversal:\n";
    Dfs::preorder(root);

    // 中序遍历
    std::cout << "\nInorder traversal:\n";
    Dfs::inorder(root);

    // 后序遍历
    std::cout << "\nPostorder traversal:\n";
    Dfs::postorder(root);

    return 0;
}

利用栈实现了深度优先遍历的先序、中序和后序遍历。

通过适当地利用栈的特性,可以实现不同顺序的遍历方式。
同时,使用了智能指针std::shared_ptr来管理树节点的内存,避免了手动管理内存的复杂性。
树节点类TreeNode是一个模板类,用于存储树节点的数据和指向左右子节点的智能指针。
深度优先遍历类DfsTraversal包含了静态方法preorder、inorder和postorder,分别用于实现先序、中序和后序遍历。
每种遍历方式都是通过栈实现的,其中后序遍历还利用了两个栈的技巧。
在main函数中,构建了一棵树,并调用DfsTraversal类中的静态方法进行先序、中序和后序遍历,输出遍历结果。
#include <iostream>
#include <stack>
#include <memory> // 引入智能指针库

// 定义树节点类模板
template<typename T>
class TreeNode {
public:
    T data; // 节点数据
    std::shared_ptr<TreeNode<T>> left; // 左子节点指针
    std::shared_ptr<TreeNode<T>> right; // 右子节点指针

    // 构造函数,初始化节点数据和指针
    TreeNode(T data, std::shared_ptr<TreeNode<T>> left = nullptr, std::shared_ptr<TreeNode<T>> right = nullptr)
        : data(data), left(left), right(right) {}
};

// 定义深度优先遍历类模板
class DfsTraversal {
public:
    // 先序遍历(栈)
    template<typename T>
    static void preorder(std::shared_ptr<TreeNode<T>> root) {
        if (root == nullptr) {
            return;
        }
        //定义一个栈装节点类型指针:std::shared_ptr<TreeNode<T>>
        std::stack<std::shared_ptr<TreeNode<T>>> stack;
        //将根节点压栈
        stack.push(root);
        
        //如果栈不为空,则进行压右右节点再压左节点,并且将目前根节点,打印出来后出栈
        while (!stack.empty()) {
            auto node = stack.top();
            process(node);
            
            stack.pop();

            // 先压右子节点,再压左子节点
            if (node->right != nullptr) {
                stack.push(node->right);
            }
            if (node->left != nullptr) {
                stack.push(node->left);
            }
        }
    }

    // 中序遍历(栈)
	template<typename T>
	static void inorder(std::shared_ptr<TreeNode<T>> root) {
	    // 如果根节点为空,则直接返回
	    if (root == nullptr) {
	        return;
	    }
	
	    // 创建一个栈,用于存储遍历过程中的节点
	    std::stack<std::shared_ptr<TreeNode<T>>> stack;
	    // 初始化一个指针current指向根节点
	    auto current = root;
	
	    // 当前节点不为空,或者栈不为空时,继续遍历
	    while (current != nullptr || !stack.empty()) {
	        // 将当前节点及其左子节点入栈,直到当前节点为空
	        while (current != nullptr) {
	            stack.push(current);
	            current = current->left;
	        }
	        // 访问栈顶节点并出栈
	        current = stack.top();
	        // 处理当前节点,即输出其数据
	        process(current);
	        stack.pop();
	        // 将当前节点指向其右子节点,准备下一轮的遍历 
	        current = current->right;
	    }
	}


   // 后序遍历(栈)
	template<typename T>
	static void postorder(std::shared_ptr<TreeNode<T>> root) {
	    if (root == nullptr) {
	        return;
	    }
	
	    std::stack<std::shared_ptr<TreeNode<T>>> stack; // 创建一个栈用于辅助遍历
	    std::stack<std::shared_ptr<TreeNode<T>>> output; // 创建一个栈用于保存后序遍历结果
	    stack.push(root); // 将根节点入栈
	
	    // 循环遍历
	    while (!stack.empty()) {
	        auto node = stack.top(); // 获取栈顶节点
	        stack.pop(); // 弹出栈顶节点
	        output.push(node); // 将节点压入输出栈
	
	        // 先压左子节点,再压右子节点
	        if (node->left != nullptr) {
	            stack.push(node->left);
	        }
	        if (node->right != nullptr) {
	            stack.push(node->right);
	        }
	    }
	
	    // 输出后序遍历结果
	    while (!output.empty()) {
	        auto node = output.top(); // 获取输出栈顶节点
	        output.pop(); // 弹出输出栈顶节点
	        process(node); // 处理节点,即输出节点的数据
	    }
	}

private:
    // 静态方法,处理节点
    template<typename T>
    static void process(std::shared_ptr<TreeNode<T>> node) {
        std::cout << "Value = " << node->data << std::endl; // 输出节点数据
    }
};

// 主函数
int main() {
    // 构建树节点
    auto root = std::make_shared<TreeNode<int>>(1);
    root->left = std::make_shared<TreeNode<int>>(2);
    root->right = std::make_shared<TreeNode<int>>(3);
    root->left->left = std::make_shared<TreeNode<int>>(4);
    root->left->right = std::make_shared<TreeNode<int>>(5);
    root->right->left = std::make_shared<TreeNode<int>>(6);
    root->right->right = std::make_shared<TreeNode<int>>(7);

    // 先序遍历(栈)
    std::cout << "Preorder traversal (stack):\n";
    DfsTraversal::preorder(root);

    // 中序遍历(栈)
    std::cout << "\nInorder traversal (stack):\n";
    DfsTraversal::inorder(root);

    // 后序遍历(栈)
    std::cout << "\nPostorder traversal (stack):\n";
    DfsTraversal::postorder(root);

    return 0; // 返回0表示程序正常结束
}

利用队列实现了广度优先遍历。

定义了一个树节点类模板 TreeNode<T>,
其中包含节点数据和左右子节点指针,
使用了智能指针 std::shared_ptr 进行节点内存管理。
然后定义了一个广度优先遍历函数 bfs,使用队列实现。
在 main 函数中,构建了一颗二叉树,并调用 bfs 函数进行广度优先遍历。
#include <iostream>
#include <queue>
#include <memory> // 引入智能指针库

// 定义树节点类模板
template<typename T>
class TreeNode {
public:
    T data; // 节点数据
    std::shared_ptr<TreeNode<T>> left; // 左子节点指针,使用智能指针
    std::shared_ptr<TreeNode<T>> right; // 右子节点指针,使用智能指针

    // 构造函数,初始化节点数据和指针
    TreeNode(T data, std::shared_ptr<TreeNode<T>> left = nullptr, std::shared_ptr<TreeNode<T>> right = nullptr)
        : data(data), left(left), right(right) {}
};

// 使用队列实现广度优先遍历
template<typename T>
void bfs(std::shared_ptr<TreeNode<T>> root) {
    if (root == nullptr) {
        return;
    }

    std::queue<std::shared_ptr<TreeNode<T>>> queue; // 创建队列对象,存储智能指针
    queue.push(root); // 将根节点入队

    while (!queue.empty()) { // 当队列不为空时循环
        std::shared_ptr<TreeNode<T>> node = queue.front(); // 获取队首节点
        queue.pop(); // 出队

        // 遍历节点
        std::cout << "Value = " << node->data << std::endl;

        // 将左子节点入队
        if (node->left != nullptr) {
            queue.push(node->left);
        }

        // 将右子节点入队
        if (node->right != nullptr) {
            queue.push(node->right);
        }
    }
}

int main() {
    // 构建树节点,使用智能指针进行管理
    auto root = std::make_shared<TreeNode<int>>(1);
    root->left = std::make_shared<TreeNode<int>>(2);
    root->right = std::make_shared<TreeNode<int>>(3);
    root->left->left = std::make_shared<TreeNode<int>>(4);
    root->left->right = std::make_shared<TreeNode<int>>(5);
    root->right->left = std::make_shared<TreeNode<int>>(6);
    root->right->right = std::make_shared<TreeNode<int>>(7);

    // 广度优先遍历使用队列
    std::cout << "BFS using queue and smart pointers:\n";
    bfs(root);

    return 0; // 返回0表示程序正常结束
}

如有错误请指出,谢谢大家

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值