Algorithm 二叉树的打印边界
如何打印二叉树的外部框架Algorithm 二叉树的打印边界,algorithm,binary-tree,Algorithm,Binary Tree,如何打印二叉树的外部框架 顺序是从上到下,从左到右,然后从下到上 打印所有最左侧节点和最右侧节点 打印所有叶节点 打印只有一个叶的所有节点 100 / \ 50 150 / \ / 24 57 130 / \ \ \ 12 30 60 132 e、 g: 输出应该是 100、50、24、12、30、57、60、130、132、150 如果我们编写三个不同的函数来打印左
100
/ \
50 150
/ \ /
24 57 130
/ \ \ \
12 30 60 132
我也在寻找一种O(n)方法,但条件是每个节点只能访问一次,不需要这个额外的O(2logn)部分。您可以通过应用于树的Euler Tour算法来实现这一点。见此: 或者(如果可以访问的话)古德里奇等人的书(链接)
我希望这有帮助看起来像是家庭作业的问题,但我需要练习。我已经十年没有做过递归了
void SimpleBST::print_frame()
{
if (root != NULL)
{
cout << root->data;
print_frame_helper(root->left, true, false);
print_frame_helper(root->right, false, true);
cout << endl;
}
}
void SimpleBST::print_frame_helper(Node * node, bool left_edge, bool right_edge)
{
if (node != NULL)
{
if (left_edge)
cout << ", " << node->data;
print_frame_helper(node->left, left_edge && true, false);
if ((!left_edge) && (!right_edge))
if ((node->left == NULL) || (node->right == NULL))
cout << node->data << ", ";
print_frame_helper(node->right, false, right_edge && true);
if (right_edge)
cout << ", " << node->data;
}
}
void SimpleBST::print_frame()
{
if(root!=NULL)
{
cout数据;
打印框架辅助对象(根->左、真、假);
打印框架辅助对象(根->右、假、真);
cout left==NULL)| |(节点->右==NULL))
cout数据正确、错误、正确和正确);
如果(右边缘)
这可以在O(n)中完成,也就是说,我们只访问树的每个节点一次。
逻辑如下
保持两个变量left和right并将其初始化为零。
当存在对左侧的递归调用时,按1递增left
当有递归调用时,骑乘侧增量右为1
从根开始,按顺序遍历并检查right是否为零,这意味着我们从未对right进行过递归调用。如果是print node,这意味着我们正在打印树的所有最左侧节点。如果right为非零,则它们不被视为边界,因此查找叶节点并打印它们
在左子树调用完成后的顺序遍历中,您冒泡到根,然后我们对右子树进行递归调用。现在,首先检查叶节点并打印它们,然后检查left是否为零,这意味着我们对left进行递归调用,因此它们不被视为边界。如果left是zero打印节点,这意味着我们正在打印树的所有最右边的节点
代码片段是
void btree::cirn(struct node * root,int left,int right)
{
if(root == NULL)
return;
if(root)
{
if(right==0)
{
cout<<root->key_value<<endl;
}
cirn(root->left,left+1,right);
if(root->left==NULL && root->right==NULL && right>0)
{
cout<<root->key_value<<endl;
}
cirn(root->right,left,right+1);
if(left==0)
{
if(right!=0)
{
cout<<root->key_value<<endl;
}
}
}
void btree::cirn(结构节点*root,int left,int right)
{
if(root==NULL)
返回;
如果(根)
{
如果(右==0)
{
coutright==NULL&&right>0)
{
cout该解决方案可以通过按预顺序-O(n)遍历树来完成。
在下面查找示例代码
Java中的示例代码:
公共类主{
/**
*打印二叉树的边界节点
*@param root-根节点
*/
公共静态void printOutsidesOfBinaryTree(节点根){
堆栈右侧=新堆栈();
堆栈=新堆栈();
布尔printingLeafs=false;
节点=根;
while(节点!=null){
//将所有非叶右节点添加到左节点
//分门别类
if(stack.isEmpty()&&printingLeafs&&
(node.left!=null | | node.right!=null)){
右侧推(节点);
}
if(node.left==null&&node.right==null){
//叶节点,打印出来
printingLeafs=true;
IO.write(节点数据);
node=stack.isEmpty()?null:stack.pop();
}否则{
如果(!printingLeafs){
IO.write(节点数据);
}
if(node.left!=null&&node.right!=null){
stack.push(node.right);
}
node=node.left!=null?node.left:node.right;
}
}
//打印出任何非叶右节点(如果有左节点)
而(!rightSide.isEmpty()){
IO.write(rightSide.pop().data);
}
}
}
算法:
打印左边界
打印树叶
打印右边界
TreeNode
定义:
class TreeNode<T> {
private T t;
private TreeNode<T> left;
private TreeNode<T> right;
private TreeNode(T t) {
this.t = t;
}
}
类树节点{
私人T;
私有树节点左;
私有树节点权;
私有树节点(T){
t=t;
}
}
这里有一个简单的解决方案:
def printEdgeNodes(root, pType, cType):
if root is None:
return
if pType == "root" or (pType == "left" and cType == "left") or (pType == "right" and cType == "right"):
print root.val
if root.left is None and root.right is None:
print root.val
if pType != cType and pType != "root":
cType = "invalid"
printEdgeNodes(root.left, cType, "left")
def printEdgeNodes(root):
return printEdgeNodes(root, "root", "root")
您可以递归地遍历每个节点并控制何时打印,下面是javascript代码片段
function findBtreeBoundaries(arr, n, leftCount, rightCount) {
n = n || 0;
leftCount = leftCount || 0;
rightCount = rightCount || 0;
var length = arr.length;
var leftChildN = 2*n + 1, rightChildN = 2*n + 2;
if (!arr[n]) {
return;
}
// this is the left side of the tree
if (rightCount === 0) {
console.log(arr[n]);
}
// select left child node
findBtreeBoundaries(arr, leftChildN, leftCount + 1, rightCount);
// this is the bottom side of the tree
if (leftCount !== 0 && rightCount !== 0) {
console.log(arr[n]);
}
// select right child node
findBtreeBoundaries(arr, rightChildN, leftCount, rightCount + 1);
// this is the right side of the tree
if (leftCount === 0 && rightCount !== 0) {
console.log(arr[n]);
}
}
findBtreeBoundaries([100, 50, 150, 24, 57, 130, null, 12, 30, null, 60, null, 132]);
O(n+2logn)
isO(n)
@interjay是对的,我们可以跳过常量部分,它等于O(n)检查一下。它的时间和空间复杂性与简单遍历相同algo@interjay我知道O(n+2logn)是O(n),但我说的是不同的..算法应该只访问每个节点一次。检查这个。它将只遍历每个节点一次。它使用递归。我认为这不会在OP的问题中打印130。
function findBtreeBoundaries(arr, n, leftCount, rightCount) {
n = n || 0;
leftCount = leftCount || 0;
rightCount = rightCount || 0;
var length = arr.length;
var leftChildN = 2*n + 1, rightChildN = 2*n + 2;
if (!arr[n]) {
return;
}
// this is the left side of the tree
if (rightCount === 0) {
console.log(arr[n]);
}
// select left child node
findBtreeBoundaries(arr, leftChildN, leftCount + 1, rightCount);
// this is the bottom side of the tree
if (leftCount !== 0 && rightCount !== 0) {
console.log(arr[n]);
}
// select right child node
findBtreeBoundaries(arr, rightChildN, leftCount, rightCount + 1);
// this is the right side of the tree
if (leftCount === 0 && rightCount !== 0) {
console.log(arr[n]);
}
}
findBtreeBoundaries([100, 50, 150, 24, 57, 130, null, 12, 30, null, 60, null, 132]);