20190401学习内容

一. 数据结构-二叉树

1. 创建一个二叉树的结点类:
代码实现

  package tree;

/**
 * @Author: qianwen
 * @Date: 2019/4/1
 * @Description:创建一个二叉树的结点类
 */
public class TreeNode {
    int val;
    TreeNode left = null;
    TreeNode right = null;

    TreeNode(int x){
        val = x;
    }
}

2. 剑指offer面试题
(1)根据前序和中序遍历结果重构二叉树
涉及知识点:
前序遍历二叉树:

  1. 遍历顺序:根节点—》左子树—》右子树
    中序遍历二叉树:

  2. 遍历顺序:左子树—》根节点—》右子树
    题目:
    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
    代码实现:

    package tree;
     
     import java.util.Arrays;
     
     /**
      * @Author: qianwen
      * @Date: 2019/4/1
      * @Description:根据前序和中序遍历结果重构二叉树
      */
     public class ReConstructBinaryTree {
         //@param: int [] pre 前序遍历的序列,int [] in 中序遍历的序列
         public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
             //算法思路:数组pre的第一个元素是根节点,从in数组中找到根节点,根节点左边是左子树,根节点右边是右子树,通过递归可继续
             // 得到左右子树的根节点
     
             //异常情景:
             if (pre == null || in == null){
                 return null;
             }
             if (pre.length == 0 || in.length == 0){
                 return null;
             }
             if (pre.length != in.length){
                 return null;
             }
     
             //正常情景:
             TreeNode root = new TreeNode(pre[0]);
             //遍历数组in,查找与根节点值相同的元素
             for (int i = 0; i < in.length; i++){
                 if (pre[0] == in[i]){
                     //取左子树进行递归
                     root.left = reConstructBinaryTree(
                             Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
                     //取右子树进行递归
                     root.right = reConstructBinaryTree(
                             Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
                 }
             }
             return root;
         }
     
         public static void main(String[] args) {
             ReConstructBinaryTree rcb = new ReConstructBinaryTree();
             TreeNode result = rcb.reConstructBinaryTree(new int[]{1,2,4,7,3,5,6,8}, new int[]{4,7,2,1,5,3,8,6});
             System.out.println("根节点的值是:" + result.val);
             System.out.println("左子树的根节点值是:" + result.left.val);
             System.out.println("右子树的根节点值是:" + result.right.val);
     
         }
     }
    

    (2)层序遍历二叉树
    涉及知识点:
    层序遍历二叉树:

    1. 遍历顺序:从根节点开始,每层按从左到右的顺序遍历二叉树
      题目:
      从上往下打印出二叉树的每个节点,同层节点从左至右打印。
      代码实现:
      public class PrintFromTopToBottom {
      public ArrayList printFromTopToBottom(TreeNode root) {
      //异常case:
      if (root == null)
      return null;

       //算法思路:利用LinkedList类可“尾进头出”的特点,层序遍历二叉树
       //正常case:
       //用来存储遍历的二叉树结点的值
       ArrayList<Integer> arrayList = new ArrayList<>();
      
       //可实现队列、栈,支持按索引查找元素
       LinkedList<TreeNode> queue = new LinkedList<>();
      
       //将根节点塞进队列中
       queue.add(root);
      
       while (!queue.isEmpty()) {
      
           //获取并删除队列的第一个元素,**java中没有封装专门实现队列的类?**
           TreeNode node = queue.poll();
      
           //将队列中第一个结点的值塞到集合中
           arrayList.add(node.val);
      
           //若左子树非空,将左子树的根节点塞进队列中
           if (node.left != null) {
               queue.addLast(node.left);
           }
      
           //若右子树非空,将右子树的根节点塞进队列中
           if (node.right != null) {
               queue.addLast(node.right);
           }
       }
       return arrayList;
      

      }

      //测试脚本
      public static void main(String[] args) {
      TreeNode root = new TreeNode(1);
      root.left = new TreeNode(2);
      root.right = new TreeNode(3);
      root.left.left = new TreeNode(4);
      root.left.right = new TreeNode(5);

       PrintFromTopToBottom pr = new PrintFromTopToBottom();
       ArrayList result = pr.printFromTopToBottom(root);
       for (Object i : result){
           System.out.println(i);
       }
      

      }
      }

补充Java语言基础知识点:
Queue接口

  1. 实现了队列的数据结构
  2. 接口提供的方法:
    插入元素:add() 将指定元素插入队列的尾部
    offer() 将指定元素插入队列的尾部,更适合有容量限制的队列

获取元素:element() 获取队列头部的元素,但是不删除该元素
peek() 获取队列头部的元素,但是不删除该元素。当队列为空时,返回null
remove() 获取队列头部的元素,并删除该元素
poll() 获取队列头部的元素,并删除该元素。当队列为空时,返回null

Deque接口

  1. 是Queue接口的子接口
  2. 实现了“双端队列”的数据结构
  3. 接口提供的方法
    插入元素:addFirst()
    addLast()
    offerFirst()
    offerLast()

    获取元素:getFirst() 获取并不删除队列的第一个元素
    getLast() 获取并不删除队列的最后一个元素
    peekFirst() 获取并不删除队列的第一个元素,若双端队列为空,则返回null
    peekLast() 获取并不删除队列的最后一个元素,若双端队列为空,则返回null
    pollFirst()
    pollLast()

    removeFirst()
    removeLast()
    栈方法: pop()
    push()

Deque的实现类:
4. ArrayDeque:可实现栈和队列,底层是一个数组,长度默认是16---->可以代替Stack
5. LinkedList:可实现栈和队列,还实现了List接口,底层是一个链表

(3)后序遍历二叉搜索/排序树
涉及知识点:
后序遍历二叉树:
1. 遍历顺序:左子树—》右子树—》根节点
二叉搜索树:
它或者是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
题目:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
代码实现:

public class VerifySquenceOfBST {
    public boolean verifySquenceOfBST(int[] sequence) {
        if (sequence == null || sequence.length == 0)
            return false;
        int rstart = 0;
        int length = sequence.length;

        //数组的最后一个元素,是根节点
        //从数组的第一个元素查找,第一个大于根节点的元素
        for (int i = 0; i <= length - 2; i++) {
            if (sequence[i] < sequence[length - 1])
                rstart++;
        }

        //rstart == 0 ==>说明没有左子树
        if (rstart == 0) {
            verifySquenceOfBST(Arrays.copyOfRange(sequence,0,length-1));
        }else {
            //restart > 0 ==>说明有左子树
            //如果从第一个大于根节点的元素开始,到根节点前面一位的元素,值都大于根节点,则进行下一步;否则直接false;
            for (int i = rstart; i <= length - 2; i++) {
                if (sequence[i] <= sequence[length - 1]) {
                    return false;
                }
            }
            //开始遍历左子树
            verifySquenceOfBST(Arrays.copyOfRange(sequence,0,rstart));
            //开始遍历右子树
            verifySquenceOfBST(Arrays.copyOfRange(sequence,rstart,length - 1));
        }
        return true;
    }

    public static void main(String[] args) {
        VerifySquenceOfBST v = new VerifySquenceOfBST();
        System.out.println(v.verifySquenceOfBST(new int[]{4,5,2,3}));
    }
}

//算法思路:https://blog.csdn.net/xidiancoder/article/details/60956436

(4)输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
题目:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
代码实现:

public class HasSubtree {
public boolean hasSubtree(TreeNode root1,TreeNode root2) {
    //此处root == null是为了判断第二个二叉树一开始是不是空树
    if (root1 == null && root2 == null)
        return false;

    //若root1和root2均不为空,1.比较树1和树2是否相同;2.比较树1的左子树和树2是否相同;3.比较树1的右子树和树2是否相同
    return isSubTree(root1,root2) || hasSubtree(root1.left,root2) || hasSubtree(root1.right,root2);
}

public boolean isSubTree(TreeNode root1,TreeNode root2){
    //此处return返回true,是直至第二个二叉树已经遍历完成,均和第一个二叉树的结点相同
    if (root2 == null){
        return true;
    }
    if (root1 == null){
        return false;
    }
    if (root1.val == root2.val){
        return isSubTree(root1.right, root2.right) && isSubTree(root1.left, root2.left);
    }
    return false;
}

public static void main(String[] args) {
    //创建第一颗树
    TreeNode root1 = new TreeNode(1);
    root1.left = new TreeNode(2);
    root1.right = new TreeNode(3);
    root1.left.left = new TreeNode(4);
    root1.left.right = new TreeNode(5);

    //创建第二颗树
    TreeNode root2 = new TreeNode(1);
    root2.left = new TreeNode(2);
    root2.right = new TreeNode(3);
    root2.left.left = new TreeNode(8);

    HasSubtree hasSubtree = new HasSubtree();
    System.out.println(hasSubtree.hasSubtree(root1,root2));
}

}
这种解法有问题

(4)操作给定的二叉树,将其变换为源二叉树的镜像
题目:
操作给定的二叉树,将其变换为源二叉树的镜像
代码实现:
方法1:递归实现

public class Mirror {
public void mirror(TreeNode root) {
    if (root == null)
        return;

    //保证二叉树的左右子树至少存在一个
    if (root != null && (root.left != null || root.right != null)){
        //交换左右子树
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        //递归调用继续交换下一个左右子树
        mirror(root.left);
        mirror(root.right);
    }
}
}
方法2. 循环
 public void mirror(TreeNode root) {
    //方法2:循环
    if (root == null)
        return;

    **//java中的栈怎么实现的?**
    Stack<TreeNode> stack = new Stack<>();
    
    while (root != null || !stack.isEmpty()) {
        while (root != null) {
            //将根结点的左右子树相互交换
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            
            //将根结点塞进栈中
            stack.push(root);
            //继续交换左子树的结点
            root = root.left;
        }
        //**这一步是为啥?**
        if (!stack.isEmpty()) {
            root = stack.pop();
            root = root.right;
        }
    }
}

补充知识点:
Java中的Stack类实现

  1. 继承自Vector类
  2. 底层也是数组,默认长度10
  3. 线程安全,性能不好
  4. Stack提供的方法:peek() peek() push()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值