笔试习题练习

1.伙伴地址 

二进制地址为011011110000,大小为(4)10和(16)10块的伙伴地址分别为:_________,_________。

地址011011110000,可以被2^(2+1)整除,所以伙伴地址是其下半部,加4就行,所以答案是011011110100;
16大小时,不能被2^(4+1)整除,所以伙伴地址是其上半部,地址减去16,结果为0110 1110 0000。至于为什么这样整除决定,请查看伙伴地址定义

2.如何判断一棵二叉树是否是平衡二叉树

平衡二叉树的定义,如果任意节点的左右子树的深度相差不超过1,那这棵树就是平衡二叉树。

算法思路:先编写一个计算二叉树深度的函数GetDepth,利用递归实现;然后再递归判断每个节点的左右子树的深度是否相差1

static int GetDepth(BinNode root)
{
    if (root == null)
        return 0;
    int leftLength = GetDepth(root.Left);
    int rightLength = GetDepth(root.Right);
    return (leftLength > rightLength ? leftLength : rightLength) + 1;
}

 

注意这里的+1,对应于root不为空(算作当前1个深度)

static bool IsBalanceTree(BinNode root)
{
    if (root == null)
        return true;
    int leftLength = GetDepth(root.Left);
    int rightLength = GetDepth(root.Right);
    int distance = leftLength > rightLength ? leftLength - rightLength : rightLength - leftLength;
    
    if (distance > 1)
        return false;
    else 
        return IsBalanceTree(root.Left) && IsBalanceTree(root.Right);
}
 

上述程序的逻辑是,只要当前节点root的Left和Right深度差不超过1,就递归判断Left和Right是否也符合条件,直到为Left或Right为null,这意味着它们的深度为0,能走到这一步,前面必然都符合条件,所以整个二叉树都符合条件。


3.如何不用递归实现二叉树的前序/后序/中序遍历?

算法思想:三种算法的思想都是让root的Left的Left的Left全都入栈。所以第一个while循环的逻辑,都是相同的。

下面详细分析第2个while循环,这是一个出栈动作,只要栈不为空,就始终要弹出栈顶元素,由于我们之前入栈的都是Left节点,所以每次在出栈的时候,我们都要考虑Right节点是否存在。因为前序/后序/中序遍历顺序的不同,所以在具体的实现上有略为区别。

1)前序遍历

这个是最简单的。

前序遍历是root->root.Left->root.Right的顺序。

因为在第一个while循环中,每次进栈的都可以认为是一个root,所以我们直接打印,然后root.Right和root.Left先后进栈,那么出栈的时候,就能确保先左后右的顺序。

static void PreOrder(BinNode root)
{
    Stack stack = new Stack();
    BinNode temp = root;
    //入栈
    while (temp != null)
    {
        Console.WriteLine(temp.Element);
        if (temp.Right != null)
            stack.Push(temp.Right);
        temp = temp.Left;
    }
    //出栈,当然也有入栈
    while (stack.Count > 0)
    {
        temp = (BinNode)stack.Pop();
        Console.WriteLine(temp.Element);
        while (temp != null)
        {
            if (temp.Right != null)
                stack.Push(temp.Right);
            temp = temp.Left;
        }
    }
}
//后序遍历比较麻烦,需要记录上一个访问的节点,然后在本次循环中判断当前节点的Right或Left是否为上个节点,当前节点的Right为null表示没有右节点。
static void PostOrder(BinNode root)
{
    Stack stack = new Stack();
    BinNode temp = root;
    //入栈
    while (temp != null)
    {
        if (temp != null)
            stack.Push(temp);
        temp = temp.Left;
    }
    //出栈,当然也有入栈
    while (stack.Count > 0)
    {
        BinNode lastvisit = temp;
        temp = (BinNode)stack.Pop();
        if (temp.Right == null || temp.Right == lastvisit)
        {
            Console.WriteLine(temp.Element);
        }
        else if (temp.Left == lastvisit)
        {
            stack.Push(temp);
            temp = temp.Right;
            stack.Push(temp);
            while (temp != null)
            {
                if (temp.Left != null)
                    stack.Push(temp.Left);
                temp = temp.Left;
            }
        }
    }
}
//中序遍历,类似于前序遍历
static void InOrder(BinNode root)
{
    Stack stack = new Stack();
    BinNode temp = root;
    //入栈
    while (temp != null)
    {
        if (temp != null)
            stack.Push(temp);
        temp = temp.Left;
    }
    //出栈,当然也有入栈
    while (stack.Count > 0)
    {
        temp = (BinNode)stack.Pop();
        Console.WriteLine(temp.Element);
        if (temp.Right != null)
        {
            temp = temp.Right;
            stack.Push(temp);
            while (temp != null)
            {
                if (temp.Left != null)
                    stack.Push(temp.Left);
                temp = temp.Left;
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值