【常见算法系列】一、树在java中的实现

一、定义

1 二叉树

1、定义:每个结点最多能够有两个子节点
2、性质:

  1. 二叉树的第i层上至多有2i-1(i≥1)个节点。
  2. 深度为h的二叉树中至多含有2h-1个节点 。
  3. 若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0=n2+1 。
    4在这里插入图片描述

2 满二叉树

如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树 。
在这里插入图片描述

3 完全二叉树

1、定义
深度为k,有n个结点的二叉树当且仅当其每一个结点都与深度为k的满二叉树中编号从1到n的结点一一对应时,称为完全二叉树 。
2、性质

  1. 具有n个节点的完全二叉树深为log2x+1(其中x表示不大于n的最大整数)。
  2. 若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:
    A、当i=1时,该节点为根,它无双亲节点 [6] 。
    B、当i>1时,该节点的双亲节点的编号为i/2 [6] 。
    C、若2i≤n,则有编号为2i的左节点,否则没有左节点 [6] 。
    D、若2i+1≤n,则有编号为2i+1的右节点,否则没有右节点 [6] 。
    在这里插入图片描述

4 二叉搜索树

  1. 或者是一棵空树
  2. 或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
  3. 二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势
    在这里插入图片描述

5 平衡二叉树

平衡二叉树的提出就是为了保证树不至于太倾斜,尽量保证两边平衡。因此它的定义如下:

  1. 平衡二叉树要么是一棵空树
  2. 要么保证左右子树的高度之差不大于 1
  3. 子树也必须是一颗平衡二叉树
  4. 在这里插入图片描述

6 平衡二叉查找树

平衡二叉搜索树是一种结构平衡的二叉搜索树,特点:

  1. 叶节点高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
  2. 它能在O(n)内完成插入、查找和删除操作

7 B树

即二叉搜索树:

  1. 所有非叶子结点至多拥有两个儿子(Left和Right);
  2. 所有结点存储一个关键字;
  3. 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树
    在这里插入图片描述

8、 B-树

是一种多路搜索树(并不是二叉的):

  1. 定义任意非叶子结点最多只有M个儿子;且M>2;
  2. 根结点的儿子数为[2, M];
  3. .除根结点以外的非叶子结点的儿子数为[M/2, M];
  4. 每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
  5. 非叶子结点的关键字个数=指向儿子的指针个数-1;
  6. .非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
  7. 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1],K[i])的子树;
  8. 所有叶子结点位于同一层;
    9在这里插入图片描述

9、B+树

B+树是B-树的变体,也是一种多路搜索树:
1.其定义基本与B-树同,除了:
2.非叶子结点的子树指针与关键字个数相同;
3.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);
5.为所有叶子结点增加一个链指针;
6.所有关键字都在叶子结点出现;
在这里插入图片描述

10、B*树

B*树是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
在这里插入图片描述

二、算法题
2.1 二叉树前序、中序和后序遍历

在这里插入图片描述
1、递归:

public class Solution {

    public int[][] threeOrders (TreeNode root) {
        

        List<Integer> preList = new ArrayList<Integer>();
        preOrder(root, preList);
        
        List<Integer> inList = new ArrayList<Integer>();
        inOrder(root, inList);

       List<Integer> postList = new ArrayList<Integer>();
       postOrder(root, postList );
       int[][] resArray = new int[3][preList.size()];

        for(int i=0; i< preList.size(); i++) {
            resArray[0][i] = preList.get(i);
            resArray[1][i] = inList.get(i);
            resArray[2][i] = postList.get(i);
        }
        return resArray;
        
    }
    
    void preOrder(TreeNode root, List<Integer> list) {
        if(root == null) {
            return ;
        }
        list.add(root.val);
        preOrder(root.left, list);
        preOrder(root.right, list);

    }
    
     void inOrder(TreeNode root, List<Integer> list) {
        if(root == null) {
            return ;
        }
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right, list);

    }
    
     void postOrder(TreeNode root, List<Integer> list) {
        if(root == null) {
            return ;
        }
        postOrder(root.left, list);
        postOrder(root.right, list);
        list.add(root.val);
    }
}

2、栈

 public int[][] threeOrders(TreeNode root) {


        
        List<Integer> preList = new ArrayList<Integer>();
        preOrder(root, preList);

        List<Integer> inList = new ArrayList<Integer>();
        inOrder(root, inList);

        List<Integer> postList = new ArrayList<Integer>();
        postOrder(root, postList);
        int[][] resArray = new int[3][preList.size()];

        for (int i = 0; i < preList.size(); i++) {
            resArray[0][i] = preList.get(i);
            resArray[1][i] = inList.get(i);
            resArray[2][i] = postList.get(i);
        }
        return resArray;

    }

    void preOrder(TreeNode root, List<Integer> list) {
        if (root == null) {
            return;
        }
        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            list.add(node.val);

            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }

    }

    void inOrder(TreeNode root, List<Integer> list) {
        if (root == null) {
            return;
        }

        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode curr = root;
        while (!stack.isEmpty() || curr != null) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            
            curr = stack.pop();
            list.add(curr.val);
            curr = curr.right;


        }


    }


    void postOrder(TreeNode root, List<Integer> list) {

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode curr = stack.pop();
            list.add(0, curr.val);
            if (curr.left != null) {
                stack.push(curr.left);
            }
            if (curr.right != null) {
                stack.push(curr.right);
            }
        }

    }

2.4、二叉树层次遍历bfs

描述
给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
在这里插入图片描述
该二叉树层序遍历的结果是

[ [3], [9,20], [15,7] ]

 public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
         ArrayList<ArrayList<Integer>>  resultList = new ArrayList<ArrayList<Integer>>();

        if(root == null) {
            return resultList;
        }
        // write code here
        ArrayDeque<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.addLast(root);
        
        ArrayDeque<TreeNode> tmpQueue = new ArrayDeque<TreeNode>();
        

        ArrayList<Integer> tmpList = new ArrayList<Integer>();
        while(!queue.isEmpty()) {
            
            TreeNode node =  queue.pollFirst();
            tmpList.add(node.val);
            
            if(node.left != null) {
               tmpQueue.addLast(node.left); 
            }
            
            if(node.right != null) {
               tmpQueue.addLast(node.right); 
            }
            
            if(queue.isEmpty()) {
                
                queue = tmpQueue;
                tmpQueue = new ArrayDeque<TreeNode>();
                resultList.add(tmpList);
                 tmpList = new ArrayList<Integer>();
            }
            
          
        }
        return resultList;
    }
2.5、二叉树深度遍历dfs
描述
给定一棵二叉树,判断其是否是自身的镜像(即:是否对称)
例如:下面这棵二叉树是对称的
  1
/  \
2     2
/ \    / \
3 4  4  3
下面这棵二叉树不对称。
1
/ \
2   2
\    \
3    3
备注:
希望你可以用递归和迭代两种方法解决这个问题

示例1
输入:{1,2,2}
返回值:true

示例2
输入:{1,2,3,3,#,2,#}
返回值:false

public class Solution {
   
    boolean flag = true;
    public boolean IsBalanced_Solution(TreeNode root) {
        depth(root);
        return flag;
    }

    private int depth(TreeNode node) {

        if(node == null) {
            return 0;
        }

        int leftDepth = depth(node.left);
        int rightDepth = depth(node.right);

        if( Math.abs(leftDepth-rightDepth) > 1 ) {
            flag =  false;
        }
        return Math.max(leftDepth, rightDepth) +1;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值