模拟卷 数据结构 复杂度分析图的遍历 解答题
第 42 题

(12 分)假设二叉树采用二叉链存储结构存储,设计一个算法,求出根结点到给定某结点之间的路径,要求:

(1)给出算法的基本设计思想。

(2)写出二叉树采用的存储结构代码。

(3)根据设计思想,采用 C 或 C++语言描述算法,关键之处给出注释。

复杂度分析 图的遍历

[tag_link]

【答案】

(1)算法的基本设计思想:采用递归的深度优先搜索(DFS)方法。从根结点开始,先序遍历二叉树,在遍历过程中使用一个动态数组(如向量)记录当前访问路径。当访问到目标结点时,当前数组中的结点序列即为根结点到目标结点的路径;如果当前结点不是目标结点,则递归遍历其左子树和右子树。若左右子树均未找到目标结点,则进行回溯,从路径中移除当前结点,并返回上一层继续搜索。这种方法利用回溯确保路径的正确性。

(2)二叉树采用的存储结构代码(C 语言描述):

typedef struct BiTNode {
    char data;                        // 结点数据,假设为字符型
    struct BiTNode *lchild, *rchild; // 左右孩子指针
} BiTNode, *BiTree;

(3)算法描述(C++ 语言,基于上述存储结构):

#include <vector>
using namespace std;

// 函数功能:查找从根结点到目标结点的路径
// 参数:root 为当前子树根结点,target 为目标结点,path 用于存储路径
// 返回值:bool 类型,找到路径返回 true,否则返回 false
bool findPath(BiTree root, BiTree target, vector<BiTree> &path) {
    if (root == nullptr) return false;            // 空树,直接返回 false
    path.push_back(root);                         // 当前结点加入路径
    if (root == target) return true;              // 找到目标结点,返回 true
    if (findPath(root->lchild, target, path)) return true;  // 递归搜索左子树
    if (findPath(root->rchild, target, path)) return true;  // 递归搜索右子树
    path.pop_back();                              // 左右子树均未找到,回溯,移除当前结点
    return false;
}
// 调用示例:假设 root 为根结点指针,target 为目标结点指针,path 为空的 vector<BiTree> 类型,
// 调用 findPath(root, target, path) 后,若返回 true,则 path 中存储从根到目标的路径结点序列。

【解析】算法的核心思想是递归深度优先搜索,结合回溯记录路径。从根结点开始,先访问当前结点并加入路径,然后判断是否为给定结点:若是则成功;否则递归搜索左子树和右子树。递归调用前将当前结点加入路径,调用后若子树中找到目标,则当前结点保留在路径中(因为它是路径的一部分),否则通过 pop_back() 移除当前结点,实现回溯。这保证了路径从根结点到目标结点的顺序性。存储结构采用二叉链,每个结点包含数据域和左右孩子指针,便于递归遍历。算法的时间复杂度为 O(n),其中 n 为二叉树结点数,最坏情况下需要遍历所有结点;空间复杂度为 O(h),h 为二叉树高度,主要由递归栈和路径向量占用,路径向量最多存储 h 个结点。该算法简洁有效,适用于二叉链存储的二叉树路径查找问题。