假设您的树具有以下结构:
struct Node
{
Node *left;
Node *right;
int value;
};
您可以在三遍中打印出所有对,并在适当的位置修改树。right
这个想法是将相同深度的节点及其指针链接在一起。您通过以下left
指针向下遍历。我们还维护每个深度的预期节点计数,因为我们不会为每个深度终止列表。然后,我们解压缩以将树恢复到其原始配置。
它的美妙之处在于zip_down
功能;它将两个子树“压缩”在一起,使得左子树的右分支指向右子树的左分支。right
如果对每个子树都执行此操作,则可以通过跟随指针遍历每个深度。
struct Node
{
Node *left;
Node *right;
int value;
};
void zip_down(Node *left, Node *right)
{
if (left && right)
{
zip_down(left->right, right->left);
left->right= right;
}
}
void zip(Node *left, Node *right)
{
if (left && right)
{
zip(left->left, left->right);
zip_down(left, right);
zip(right->left, right->right);
}
}
void print_pairs(const Node * const node, int depth)
{
int count= 1 << depth;
for (const Node *node_iter= node; count > 1; node_iter= node_iter->right, --count)
{
printf("(%c, %c) ", node_iter->value, node_iter->right->value);
}
if (node->left)
{
print_pairs(node->left, depth + 1);
}
}
void generate_tree(int depth, Node *node, char *next)
{
if (depth>0)
{
(node->left= new Node)->value= (*next)++;
(node->right= new Node)->value= (*next)++;
generate_tree(depth - 1, node->left, next);
generate_tree(depth - 1, node->right, next);
}
else
{
node->left= NULL;
node->right= NULL;
}
}
void print_tree(const Node * const node)
{
if (node)
{
printf("%c", node->value);
print_tree(node->left);
print_tree(node->right);
}
}
void unzip(Node * const node)
{
if (node->left && node->right)
{
node->right= node->left->right;
assert(node->right->value - node->left->value == 1);
unzip(node->left);
unzip(node->right);
}
else
{
assert(node->left==NULL);
node->right= NULL;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char value_generator= 'a';
Node root;
root.value= value_generator++;
generate_tree(2, &root, &value_generator);
print_tree(&root);
printf("\n");
zip(root.left, root.right);
print_pairs(&root, 0);
printf("\n");
unzip(&root);
print_tree(&root);
printf("\n");
return 0;
}
EDIT4:就地,O(n) 时间,O(log n) 堆栈空间。