关于数据结构中的二叉树

树型结构

概念
树是一种非线性的数据结构,有一个特殊的节点为根节点(无前驱节点),如下图。

  • 节点的度:一个节点含有的子树的个数
  • 树的度:一棵树中最大节点的度
  • 叶子节点(终端节点):度为0的节点
  • 双亲节点(父节点):若一个节点含有子节点,则这个节点称为其子节点的双亲节点
  • 孩子节点(子节点):一个节点含有的子树的根节点
  • 根节点:一棵树中没有双亲节点的节点
  • 节点的层次:从根开始,根为第一层,根的子节点为第二层,以此类推
  • 树的高度或深度:树中节点的最大层次

树的表现形式

  • 孩子兄弟表示法
    不仅要保存第一个孩子节点,还要给出当前节点的下一个兄弟节点
  • 双亲表示法
    节点中既要保存值域,也要保存节点双亲节点的地址
  • 孩子表示法
    节点中既要保存值域,也要保存孩子的地址
  • 孩子双亲表示法
    孩子表示和双亲表示相结合,节点中既要保存值域,也要保存节点的孩子及双亲的位置

二叉树

概念

  • 空树

  • 非空时,由一个根节点、根节点的左子树及根节点的右子树组成
    特点

  • 二叉树中不存在度大于2的节点

  • 二叉树是有序树
    特殊的二叉树
    (1)满二叉树:二叉树中每层结点的个数达到了最大值
    (2)完全二叉树:一棵具有n个节点的二叉树与满二叉树前n个节点的连接形式一样。满二叉树是特殊的完全二叉树。
    性质
    (1)若规定根节点的曾树为1,则一棵非空二叉树的第i(i>0)层上最多有2^(i-1)个节点;
    (2)若规定只有根节点的二叉树的深度为1,则深度为k(k>=0)的二叉树的最大节点数为2^k-1;
    (3)对任何一棵二叉树,若其叶节点个数为n0,度为2的非叶节点个数为n2,则有n0=n2+1;
    (4)具有n个节点的完全二叉树的深度k为log2(n+1)上取整,若为满二叉树,计算出的一定是整数;
    (5)对于具有n个节点的完全二叉树,如果按照从上至下、从左至右的顺序对所有节点从0开始编号,则对于序号为i的节点有:
    ①若i>0,双亲序号:(i+1)/2;若i=0,i为根节点编号,无双亲节点
    ②若2i+1<n,左孩子序号:2i+1,否则无左孩子
    ③若2i+2<n,右孩子序号:2i+2,否则无右孩子
    二叉树的存储

  • 顺序存储
    以数组的形式存储

  • 链式存储
    通过一个一个的节点引用起来

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

二叉树的遍历
(1)层序遍历
(2)根据遍历根节点的先后次序:

  • 前序遍历
    根节点->根节点的左子树->根节点的右子树
  • 中序遍历
    根节点的左子树->根节点->根节点的右子树
  • 后序遍历
    根节点的左子树->根节点的右子树->根节点
    二叉树的基本操作
  • 前序遍历
//前序递归遍历
public void preOrder(BTNode root){
        if(null != root) {
            System.out.println(root.val + " ");
            preOrder(root.left);
            preOrder(root.right);
        }
    }
//前序非递归遍历
public void preOrderTraversel(BTNode root){
        if(null == root){
            return;
        }
        Stack<BTNode> s = new Stack<>();
        s.push(root);
        while(!s.isEmpty()){
            BTNode cur = s.peek();
            System.out.print(cur.val + " ");
            s.pop();


            //如果cur有右子树,让右子树入队列
            if(null != cur.right){
                s.push(cur.right);
            }

            //如果cur有左子树,让左子树入队列
            if(null != cur.left){
                s.push(cur.left);
            }
        }
        System.out.println();
    }
  • 中序遍历
//中序递归遍历
public void inOrder(BTNode root){
        if(null != root){
            inOrder(root.left);
            System.out.println(root.val + " ");
            inOrder(root.right);
        }
    }
//中序非递归遍历
public void inOrderTraversel(){
        if(null == root){
            return;
        }
        Stack<BTNode> s = new Stack<>();
        BTNode cur = root;
        while(null != cur || !s.empty()){
            while(cur != null){
                s.push(cur);
                cur = cur.left;
            }
            cur = s.peek();
            System.out.print(cur.val + " ");
            s.pop();
            cur = cur.right;
        }
    }
  • 后序遍历
//后序递归遍历
private void postOrder(BTNode root){
        if(null != root){
            postOrder(root.left);
            postOrder(root.right);
            System.out.println(root.val + " ");
        }
    }
//后序非递归遍历
public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ret = new ArrayList<>();
        if(root == null){
            return ret;
        }
        Stack<TreeNode> s = new Stack<>();
        s.push(root);
        while(!s.isEmpty()){
            TreeNode cur = s.pop();
            if(cur.left != null){
                s.push(cur.left);
            }
            if(cur.right != null){
                s.push(cur.right);
            }
            ret.add(0, cur.val);
        }
        return ret;
    }
  • 层序遍历
//层序遍历
    public void levelOrder(){
        if(null == root){
            return;
        }
        Queue<BTNode> q = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()){
            BTNode cur = q.poll();
            System.out.print(cur.val + " ");

            //如果cur有左子树,让左子树入队列
            if(null != cur.left){
                q.offer(cur.left);
            }

            //如果cur有右子树,让右子树入队列
            if(null != cur.right){
                q.offer(cur.right);
            }
        }
        System.out.println();
    }
  • 获取二叉树中节点的个数
public int getCount(BTNode root){
        if(null == root){
            return 0;
        }
        return 1 + getCount(root.left) + getCount(root.right);
    }
  • 获取叶子结点个数
public int getLeafCount(BTNode root){
        if(null == root){
            return 0;
        }
        if(root.left == null && root.right == null){
            return 1;
        }
        return getLeafCount(root.left) + getLeafCount(root.right);
    }
  • 获取第k层节点个数
public int getKLevelCount(BTNode root, int k){
        if(null == root){
            return 0;
        }
        if(k < 1){
            return 0;
        }
        if(k == 1){
            return 1;
        }
        return getKLevelCount(root.left, k - 1) + getKLevelCount(root.right, k - 1);
    }
  • 求二叉树高度
private int getHeight(BTNode root){
        if(null == root){
            return 0;
        }
        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);
        return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
    }

猜你喜欢

转载自blog.csdn.net/qq_43452252/article/details/104742725