我最近意识到虽然在我的生活中使用了BST,但我甚至都没有考虑使用任何东西,除了Inorder遍历(虽然我知道并且知道调整程序使用前/后顺序是多么容易遍历)。
在意识到这一点后,我拿出了一些旧的数据结构教科书,并寻找了预订和后序遍历的有用性背后的推理 - 但他们并没有说太多。
什么时候实际使用预订单/后期订单的例子是什么?什么时候比按顺序更有意义?
答案 0 :(得分:107)
在您了解在什么情况下使用二叉树的预订,有序和后期订单之前,您必须准确了解每种遍历策略的工作原理。以下面的树为例。
树的根 7 ,最左边的节点 0 ,最右边的节点 10 。
预订遍历:
摘要:从根开始( 7 ),在最右边的节点( 10 )结束
遍历序列:7,1,0,3,2,5,4,6,9,8,10
有序遍历:
摘要:从最左边的节点开始( 0 ),在最右边的节点( 10 )结束
遍历序列:0,1,2,3,4,5,6,7,8,9,10
订单后遍历:
摘要:从最左边的节点开始( 0 ),以根( 7 )结束
遍历序列:0,2,4,6,5,3,1,8,10,9,7
程序员选择的遍历策略取决于所设计算法的特定需求。目标是速度,因此选择能够为您提供最快的节点的策略。
如果您知道在检查任何树叶之前需要探索根部,则选择预订,因为您将在所有树叶之前遇到所有树根。
如果您知道需要在任何节点之前探索所有树叶,请选择后期订单,因为您不会浪费任何时间检查根来搜索树叶。
如果您知道树在节点中具有固有序列,并且您希望将树展平为原始序列,则应使用按顺序遍历。树将以与创建时相同的方式展平。预订或后序遍历可能无法将树展开回到用于创建它的序列中。
struct Node{
int data;
Node *left, *right;
};
void preOrderPrint(Node *root)
{
print(root->name); //record root
if (root->left != NULL) preOrderPrint(root->left); //traverse left if exists
if (root->right != NULL) preOrderPrint(root->right);//traverse right if exists
}
void inOrderPrint(Node *root)
{
if (root.left != NULL) inOrderPrint(root->left); //traverse left if exists
print(root->name); //record root
if (root.right != NULL) inOrderPrint(root->right); //traverse right if exists
}
void postOrderPrint(Node *root)
{
if (root->left != NULL) postOrderPrint(root->left); //traverse left if exists
if (root->right != NULL) postOrderPrint(root->right);//traverse right if exists
print(root->name); //record root
}
答案 1 :(得分:22)
如果我想简单地以线性格式打印出树的分层格式,我可能会使用preorder遍历。例如:
- ROOT
- A
- B
- C
- D
- E
- F
- G
答案 2 :(得分:18)
预订/有序/订购后用法:简单的字词
预购用于创建树的副本 示例:如果要创建树的副本并且需要数组中的节点值,并且当您将索引0中的这些值插入到新树中时,您将获得副本
有序::以非递增顺序获取节点的值
订购后:如果要从树到根删除树
答案 3 :(得分:2)
前后顺序分别与自上而下和自下而上的递归算法有关。如果你想以迭代的方式在二叉树上编写给定的递归算法,这就是你基本上要做的。
进一步观察前序和后序序一起完全指定手头的树,产生紧凑的编码(对于稀疏树至少)。
答案 4 :(得分:1)
有很多地方你认为这种差异起着真正的作用。
我要指出的一个很棒的问题是编译器的代码生成。请考虑以下声明:
x := y + 32
为此生成代码的方式是(天真地,当然)首先生成用于将y加载到寄存器中的代码,将32加载到寄存器中,然后生成添加这两者的指令。因为在你操作它之前必须有一些东西(让我们假设,你总是可以做不变的操作数),你必须这样做。
一般来说,你可以得到这个问题的答案基本上减少到这个:当处理数据结构的不同部分之间存在某种依赖时,差异确实很重要。在打印元素时会看到这一点,在生成代码时(外部状态有所不同,当然也可以单独查看),或者在涉及计算的结构上进行其他类型的计算时,这取决于首先处理的子代