树—数据结构

1.树的结构及基本概念

1.1结构

树是一种非线性的数据结构,树的子树之间不能交叉

1.2基本概念

在这里插入图片描述

结点的度:一个结点含有子树的个数,如:A的度为6
树的度:所有结点的度的最大值,例如:该树的度为6
叶子结点(终端节点):度为0的结点,例如:B,C,H,I,P
双亲结点(父节点):若一个结点含有子节点,则这个结点称这个子节点的父亲结点,例如:A是B的父亲结点
孩子结点(子结点):父亲结点的子结点,例如:B是A的孩子结点
根节点:没有双亲结点的结点,例如:A是该树的根结点
树的高度(深度):树中结点的最大层次,例如:该树的深度为4
森林:有n棵互不相交的树组成的集合

1.3树的表示形式

树的表示形式有:双亲表示法,孩子表示法,孩子双亲表示法,孩子兄弟表示法,下图展示的是孩子兄弟表示法
在这里插入图片描述

2.二叉树

2.1概念

二叉树是空树或者有一个根结点加上两棵称为左子树、右子树的二叉树的有限集合

2.2三种特殊的二叉树

(1)完全二叉树:一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同在这里插入图片描述

(2)满二叉树:每层结点数都达到最大值的二叉树,就是一棵二叉树的层数为K,且结点总数为2^K-1就为满二叉树,满二叉树是一种特殊的完全二叉树在这里插入图片描述
(3)二叉搜索树:也成为二叉排序树,其左子树均小于根结点的值,右子树均大于根结点的值

2.3二叉树的性质

(1)二叉树中不存在度大于2的结点
(2)二叉树的子树有左右之分,次序不能颠倒,是有序树
(3)若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个节点
(4)若规定只有根结点的二叉树的深度为1,则深度为k的二叉树的结点总数为2^k-1
(5)对任何一棵二叉树,如果叶子结点的个数为n0,度为2的非叶子结点的个数为n2,度为1的结点个数为n1,则n0=n2+1结点总数 = n0+n1+n2
(6)具有n个结点的完全二叉树的深度为log(n+1)向上取整
(7)对于完全二叉树:已知孩子结点下标为i,则其父亲结点下标为(i-1)/2 ;已知父亲结点下标为j,则其左孩子结点下标为2j+1,右孩子结点下标为2j+2

2.4二叉树的存储

(1)顺序存储
(2)链式存储:通过一个一个的结点引用起来的,常见的表示方法有孩子表示法和孩子双亲表示法

// 孩子表示法(最常用)
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
Node parent; // 当前节点的根节点
}

2.5二叉树的手动创建

public class TestBinaryTree {
	public class TreeNode{
	    public char val;
	    public TreeNode left;
	    public TreeNode right;
	    //构造方法
	    public TreeNode(char val){
	        this.val = val;
	    }
	}
    public TreeNode crateTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        E.right = H;
        C.left = F;
        C.right = G;
        return A;//返回根节点
    }

2.6二叉树的遍历

在这里插入图片描述
(1)前序遍历
遍历顺序:根结点->左子树->右子树
遍历结果:ABDCEF

//遍历思路
     public List<Integer> preorderTraversal1(TreeNode root) {
         List<Integer> list = new ArrayList<>();
         if(root == null){
             return list;
         }
         return preorderTraversal1Child(root,list);
     }
     private List<Integer> preorderTraversal1Child(TreeNode root,List<Integer> list){
         if(root == null){
             return null;
         }
         list.add(root.val);
         preorderTraversal1Child(root.left,list);
         preorderTraversal1Child(root.right,list);
         return list;
     }
    //子问题思路
     public List<Integer> preorderTraversal2(TreeNode root) {
         List<Integer>  list = new ArrayList<>();
         if(root == null){
             return list;
         }
         list.add(root.val);
         List<Integer> leftList = preorderTraversal2(root.left);
         list.addAll(leftList);
         List<Integer> rightList = preorderTraversal2(root.right);
         list.addAll(rightList);
         return list;
     }
    //非递归实现
    public List<Integer> preorderTraversal3(TreeNode root){
        List<Integer> ret = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(cur!=null || !stack.empty()){
            while(cur != null){
                stack.push(cur);
                ret.add(cur.val);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            cur = top.right;
        }
        return ret;
    }

(2)中序遍历
遍历顺序:左子树->根结点->右子树
遍历结果:DBAECF

//中序遍历
    public void inOrder(TreeNode root){
        if (root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }
    //非递归实现
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ret = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(cur!=null||!stack.empty()){
            while(cur!=null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            ret.add(top.val);
            cur = top.right;
        }
        return ret;
    }

(3)后序遍历
遍历顺序:左子树->右子树->根结点
遍历结果:DBEFCA

//后序遍历
    public void postOrder(TreeNode root){
        if (root == null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }
    //非递归实现
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ret = new ArrayList<>();
        Stack<TreeNode> stack  = new Stack<>();
        TreeNode cur = root;
        TreeNode tmp = null;
        while(cur != null || !stack.empty()){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek();
            if(top.right == null || top.right == tmp){
                ret.add(top.val);
                stack.pop();
                tmp = top;
            }else{
                cur = top.right;
            }
        }
        return ret;
    }

(4)层序遍历
遍历结果:ABCDEF

public void leaveOrder(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<>();
        if (root != null){
            queue.offer(root);
        }
        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();
            System.out.print(cur.val+" ");
            if (cur.left != null){
                queue.offer(cur.left);
            }
            if (cur.right != null){
                queue.offer(cur.right);
            }
        }
    }

2.7二叉树的基本操作

import java.util.*;
public class TestBinaryTree {
    //求二叉树节点的个数 遍历思路
    public static int countSize = 0;
    public void size1(TreeNode root){
        if (root == null){
            return;
        }
        countSize++;
        size1(root.left);
        size1(root.right);
    }
    //求二叉树节点的个数 子问题思路
    public int size2(TreeNode root){
        if (root == null){
            return 0;
        }
        return size2(root.left)+size2(root.right)+1;
    }
    //求二叉树的叶子节点的个数 遍历思路
    public static int countLeaf = 0;
    public void getLeafNodeCount1(TreeNode root){
        if (root == null){
            return;
        }
        if (root.left == null && root.right == null){
            countLeaf++;
        }
        getLeafNodeCount1(root.left);
        getLeafNodeCount1(root.right);
    }
    //求二叉树的叶子节点的个数 子问题思路
    public int getLeafNodeCount2(TreeNode root){
        if (root == null){
            return 0;
        }
        if (root.left == null && root.right == null){
            return 1;
        }
        return getLeafNodeCount2(root.left)+getLeafNodeCount2(root.right);
    }
    //求第K层节点的个数
    public int getKLevelNodeCount(TreeNode root,int k){
        if (root == null){
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
    }
    //求树的高度
    public int getHeight(TreeNode root){
        if (root == null){
            return 0;
        }
        int leftHigh = getHeight(root.left);
        int rightHigh = getHeight(root.right);
        return leftHigh > rightHigh ? leftHigh+1 : rightHigh+1;
    }
    // 检测值为value的元素是否存在
    public TreeNode find(TreeNode root, int val){
        if (root == null){
            return null;
        }
        if (root.val == val){
            return root;
        }
        TreeNode leftFind = find(root.left,val);
        if (leftFind != null){
            return leftFind;
        }
        TreeNode rightFind = find(root.right,val);
        if (rightFind != null){
            return rightFind;
        }
        return null;
    }
    //判断这棵树是不是完全二叉树
    public boolean isCompleteTree(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<>();
        //根不为空,放到队列里
        if(root != null){
            queue.offer(root);
        }
        //队列不为空,出队,如果出队不为空,将节点的左右孩子入队,否则退出循环
        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();
            if (cur != null){
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else {
                break;
            }
        }
        while (!queue.isEmpty()){
            TreeNode cur = queue.peek();
            if (cur != null){
                return false;
            }else {
                queue.poll();
            }
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值