美文网首页
(5)树相关题目

(5)树相关题目

作者: 顽皮的石头7788121 | 来源:发表于2019-03-13 10:28 被阅读0次

树是一种特殊的数据结构,包括二叉树、平衡树、B树、红黑树等众多类型。其定义为

class BinaryTreeNode {
    public int value;
    public BinaryTreeNode leftNode;
    public BinaryTreeNode rightNode;
    public BinaryTreeNode(){
    }
    public BinaryTreeNode(int value){
        this.value = value ;
        this.leftNode = null;
        this.rightNode = null;
    }
}

二叉树中常见的算法题目均可以通过迭代的方式求出。其中最典型的就是树的构建和遍历。
相关代码见https://github.com/yuanfuqiang456/LeetCode/tree/master/src/Tree

(1)二叉树的先序遍历

1、递归解法

    public static void printPreOrder1(BinaryTreeNode root) {
        if (root == null) {
            return;
        } else {
            System.out.print(root.value + " ");
        }
        if (root.leftNode != null) {
            printPreOrder1(root.leftNode);
        }
        if (root.rightNode != null) {
            printPreOrder1(root.rightNode);
        }
    }

2、非递归解法

利用栈
public static void printPreOrder2(BinaryTreeNode root) {
        Stack<BinaryTreeNode> s = new Stack<BinaryTreeNode>();
        BinaryTreeNode p = root;
             while(p!=null||!s.empty())
                 {
                     while(p!=null)
                         {
                             System.out.println(p.value);
                             s.push(p);
                             p = p.leftNode;
                         }
                     if(!s.empty())
                        {
                             p= s.lastElement();
                             s.pop();
                             p=p.rightNode;
                         }
                 }
    }

(2)二叉树的中序遍历

1、递归解法

public static void printInOrder1(BinaryTreeNode root) {
        if (root != null) {
            if (root.leftNode != null) {
                printInOrder1(root.leftNode);
            }
            System.out.print(root.value + " ");
            if (root.rightNode != null) {
                printInOrder1(root.rightNode);
            }
        }
    }

2、非递归解法

public static void printInOrder2(BinaryTreeNode root) {
        Stack<BinaryTreeNode> s = new Stack<BinaryTreeNode>();
        BinaryTreeNode p = root;
        while(p!=null||!s.empty())
        {
            while(p!=null)
            {
                s.push(p);
                p = p.leftNode;
            }
            if(!s.empty())
            {
                p= s.lastElement();
                System.out.println(p.value);
                s.pop();
                p=p.rightNode;
            }
        }
    }

(3)二叉树的后序遍历

1、递归解法

    public static void printPostOrder1(BinaryTreeNode root) {
        if (root != null) {
            if (root.leftNode != null) {
                printPostOrder1(root.leftNode);
            }
            if (root.rightNode != null) {
                printPostOrder1(root.rightNode);
            }
            System.out.print(root.value + " ");
        }
    }

2、非递归解法

public static void printPostOrder2(BinaryTreeNode root) {
        Stack<BinaryTreeNode> s = new Stack<BinaryTreeNode>();
        BinaryTreeNode cur ;
        BinaryTreeNode pre = null;
        s.push(root);
        while(!s.empty())
        {
                     cur=s.lastElement();
                     if((cur.leftNode==null&&cur.rightNode==null)||
                 (pre!=null&&(pre==cur.leftNode||pre==cur.rightNode)))
                     {
                         System.out.println(cur.value);  //如果当前结点没有孩子结点或者孩子节点都已被访问过
                         s.pop();
                         pre=cur;
                     }
                     else
                    {
                         if(cur.rightNode!=null)
                                 s.push(cur.rightNode);
                         if(cur.leftNode!=null)
                                 s.push(cur.leftNode);
                     }
                 }
         }

(4)求二叉树的深度

算法思路:使用递归的思想,分左右子树最大深度来求出。类似先序遍历。

  public static void MaxDeep(BinaryTreeNode root) {
        if(root==null)
            return 0;
        int nleft = MaxDeep(root.leftNode);
        int nright = MaxDeep(root.rightNode);
return nleft>nrigth?nleft+1:nright+1; 
}

(5)根据前序遍历和中序遍历构建二叉树

算法思路:(在不含重复数字的前提下)根据先序遍历找到根节点,然后在中序遍历中将序列分为左子序列和右子序列。递归计算。

 public static BinaryTreeNode Construct(int[] preOrder, int[] inOrder,int length){
        if (preOrder == null || inOrder == null || length <= 0) {
            return null;
        }
        try {
            return ConstructCore(preOrder, 0, preOrder.length - 1, inOrder, 0,inOrder.length - 1);
        } catch (InvalidPutException e) {
            e.printStackTrace();
            return null;
        }
    }
    public static BinaryTreeNode ConstructCore(int[] preOrder,int startPreIndex, int endPreIndex,int[] inOrder,int startInIndex, int endInIndex) throws InvalidPutException {
        int rootValue = preOrder[startPreIndex];
        System.out.println("rootValue = " + rootValue);
        BinaryTreeNode root = new BinaryTreeNode(rootValue);
        // 只有一个元素
        if (startPreIndex == endPreIndex) {
            if (startInIndex == endInIndex
                    && preOrder[startPreIndex] == inOrder[startInIndex]) {
                System.out.println("only one element");
                return root;
            } else {
                throw new InvalidPutException();
            }
        }
        // 在中序遍历中找到根结点的索引
        int rootInIndex = startInIndex;
        while (rootInIndex <= endInIndex && inOrder[rootInIndex] != rootValue) {
            ++rootInIndex;
        }
        if (rootInIndex == endInIndex && inOrder[rootInIndex] != rootValue) {
            throw new InvalidPutException();
        }
        int leftLength = rootInIndex - startInIndex;
        int leftPreOrderEndIndex = startPreIndex + leftLength;
        if (leftLength > 0) {
            // 构建左子树
            root.leftNode = ConstructCore(preOrder, startPreIndex + 1,
                    leftPreOrderEndIndex, inOrder, startInIndex,
                    rootInIndex - 1);
        }

        if (leftLength < endPreIndex - startPreIndex) {
            // 右子树有元素,构建右子树
            root.rightNode = ConstructCore(preOrder, leftPreOrderEndIndex + 1,endPreIndex, inOrder, rootInIndex + 1, endInIndex);
        }
        return root;
    }

(6)序遍历二叉树的下一个节点

算法思路:若该节点有右子树,则写一个节点为右子树的最左节点;若该节点没有右子树,且还是其父节点的左子节点,下一个节点就是父节点;若该节点即没有右子树,还是其父节点的右子节点,则下个节点为一直向上遍历,直到找到一个节点A,这个节点是原始节点的“父辈”节点,且A是A的父节点的左子节点,A即为所求。(剑指offer8题)可画图看一看。

(7)树的子结构

算法思路:判断一棵树是不是另一棵树的子结构。采用递归方法。先判断根节点,再判断左子树,右子树。

(8)二叉树的镜像

算法思路:先序遍历二叉树,若遍历到的节点有子节点,则交换两个子节点。

(9)对称的二叉树

算法思路:如果前序遍历和对称的前序遍历一致,则二叉树对称。(若一个节点子树为空,需要把空打印出来,对称前序遍历是指向遍历右子树再遍历左子树)

(10)从上到下打印二叉树

算法思路:结合队列,打印某节点,将其左右节点入队列。若要按行打印,需要维护两个变量,分别表示当前没打印的节点数和下一层的节点数。

public static void PrintFromTop(BinaryTreeNode root)
    {
        if(root==null)
        {
            return;
        }
        Queue<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>();
        queue.offer(root);
        while(queue.size()!=0)
        {
            BinaryTreeNode node = queue.peek();
            System.out.println(node.value);
            queue.poll();
            if(node.leftNode!=null)
            {
                queue.offer(node.leftNode);
            }
            if(node.rightNode!=null)
            {
                queue.offer(node.rightNode);
            }
        }
    }
    //按行打印出来
    public static void PrintFromTop2(BinaryTreeNode root)
    {
        if(root==null)
        {
            return;
        }
        Queue<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>();
        queue.offer(root);
        int nextval = 0;
        int nowval = 1;
        while(queue.size()!=0)
        {
            BinaryTreeNode node = queue.peek();
            System.out.print(node.value);
            //queue.poll();
            if(node.leftNode!=null)
            {
                queue.offer(node.leftNode);
                nextval++;
            }
            if(node.rightNode!=null)
            {
                queue.offer(node.rightNode);
                nextval++;
            }
            queue.poll();
            --nowval;
            if(nowval==0)
            {
                System.out.println();
                nowval = nextval;
                nextval = 0;
            }
        }
    }

(11)判断一棵树是不是平衡二叉树

算法思路:后序遍历,分别判断左右子树是否平衡,并求得深度。是左右子树是平衡的时候,判断左右子树深度之差。

(12)求二叉查找树的第k大元素

算法思路:中序遍历

(13)求二叉树中节点的最大距离

算法思路:左子树到跟节点的距离+右子树到跟节点的最大距离

(14)最近公共祖先

算法思路:二叉搜索树,遍历,看当前点是否大于A小于B;不是二叉搜索树,将遍历路径放到队列(或者链表)中,找最后一个公共节点。

相关文章

  • (5)树相关题目

    树是一种特殊的数据结构,包括二叉树、平衡树、B树、红黑树等众多类型。其定义为 二叉树中常见的算法题目均可以通过迭代...

  • 树相关的题目

    二叉树的构建:左子树,跟节点,右子树 二叉树的遍历:前序,中序,后序,DFS,BFS,所有路径 二叉树深度:最大深...

  • LeetCode | 树相关题目

    LeetCode 104.二叉树的最大深度 给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最...

  • 树和图相关的题目

    二叉树的序列化和反序列化:前根遍历,根的值在前面计算 最长回文子串:怎么判定回文串

  • POJ_3468 A Simple Problem with I

    1.题目相关 标签:线段树 题目地址:http://poj.org/problem?id=3468 题目大意:给定...

  • POJ_1741 男人八题

    1.题目相关 标签:树分治 题目地址:http://poj.org/problem?id=1741 题目大意:见论...

  • leetcode 226. 翻转二叉树

    题目描述 翻转一棵二叉树。相关话题: 树    难度: 简单 示例

  • 『字典树』词典中最长的单词720

    题目相关 原题链接:720. 词典中最长的单词 - 力扣(LeetCode) 涉及知识:字典树 题目难度:★ 题目...

  • 『字典树』单词的压缩编码820

    题目相关 原题链接:820. 单词的压缩编码 - 力扣(LeetCode) 涉及知识:字典树 题目难度:★★ 题目...

  • 面试题5(相关题目)

    《剑指offer》面试题5:相关题目 题目:有2个排序的数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2...

网友评论

      本文标题:(5)树相关题目

      本文链接:https://www.haomeiwen.com/subject/uvtzpqtx.html