数据结构-二叉树

二叉树指每个节点最多只能有两个子树的有序树,通常左边的子树被称为“左子树”(left subtree),右边的子树被称为“右子树”(right subtree)

普通树与二叉树的区别:

1、树中节点的最大度数没有限制,而二叉树节点的最大度数为2。

2、无序树的节点无左、右之分,而二叉树的节点有左、右之分。

满二叉树类:遵循 2^k-1个节点。

二叉树第 i 层的节点数目最多为 (i-1) 个 2 相乘 (i>=1)

实现二叉树的三种方式:

1、顺序存储:采用数组来记录二叉树的所有节点

2、二叉链表存储:每个节点保留一个 left、right域,分别指向其左、右子节点

3、三叉链表存储:每个节点保留一个left、right、parent域,分别指向其左、右子节点和父节点。

顺序存储:(造成一定的空间浪费)

import java.util.Arrays;

/**
 * Created by Administrator on 2018/3/14.
 */
public class ArrayBinTree<T> {

    //使用数组来记录该树的所有节点
    private Object[] datas;
    private int DEFAULT_DEEP = 8;
    private int deep;
    private int arraySize;

    public ArrayBinTree() {
        this.deep = DEFAULT_DEEP;
        this.arraySize = (int) Math.pow(2, deep) - 1;
        datas = new Object[arraySize];
    }

    public ArrayBinTree(int deep) {
        this.deep = deep;
        this.arraySize = (int) Math.pow(2, deep) - 1;
        datas = new Object[arraySize];
    }

    public ArrayBinTree(int deep, T data) {
        this.deep = deep;
        this.arraySize = (int) Math.pow(2, deep) - 1;
        datas = new Object[arraySize];
        datas[0] = data;
    }

    /**
     * 为指定节点添加子节点
     *
     * @param index 需要添加子节点的父节点的索引
     * @param data  新节点的数据
     * @param left  是否为左节点
     */
    public void add(int index, T data, boolean left) {
        if (datas[index] == null) {
            throw new RuntimeException(index + "处节点为空,无法添加子节点");
        }
        if (2 * index + 1 >= arraySize) {
            throw new RuntimeException("树底层的数据已满,树越界异常");
        }
        if (left) {
            datas[2 * index + 1] = data;
        } else {
            datas[2 * index + 2] = data;
        }
    }

    public boolean empty() {
        return datas[0] == null;
    }

    public T root() {
        return (T) datas[0];
    }

    //返回指定节点(非根节点)的父节点
    public T parent(int index) {
        return (T) datas[(index - 1) / 2];
    }

    public T left(int index) {
        if (2 * index + 1 >= arraySize) {
            throw new RuntimeException("该节点为叶子节点,无子节点");
        }

        return (T) datas[index * 2 + 1];
    }

    public T right(int index) {
        if (2 * index + 1 >= arraySize) {
            throw new RuntimeException("该节点为叶子节点,无子节点");
        }
        return (T) datas[index * 2 + 2];
    }


    public int deep() {
        return deep;
    }

    public int pos(T data) {
        for (int i = 0; i < arraySize; i++) {
            if (datas[i].equals(data)) {
                return i;
            }
        }
        return -1;
    }

    public String toString() {
        return Arrays.toString(datas);
    }

    public static void main(String[] args) {
        ArrayBinTree<String> binTree = new ArrayBinTree<>(4, "root");
        binTree.add(0, "第二层右子节点", false);
        binTree.add(2, "第三层右子节点", false);
        binTree.add(6, "第四层右子节点", false);
        System.out.println(binTree);
    }
}

 

链表存储:每个节点都能“记住”它的左、右两个子节点。

 

public class TwoLinkBinTree<E> {

    public static class TreeNode {
        Object data;
        TreeNode left;
        TreeNode right;

        public TreeNode() {

        }

        public TreeNode(Object data) {
            this.data = data;
        }

        public TreeNode(Object data, TreeNode left, TreeNode right) {
            this.data = data;
            this.left = left;
            this.right = right;
        }
    }

    private TreeNode root;

    public TwoLinkBinTree(E data) {
        this.root = new TreeNode(data);
    }

    public TreeNode addNode(TreeNode parent, E data, boolean isLeft) {
        if (parent == null) {
            throw new RuntimeException(parent + "节点为null,无法添加子节点");
        }
        if (isLeft && parent.left != null) {
            throw new RuntimeException("节点已有左子节点,无法添加左子节点");
        }
        if (!isLeft && parent.right != null) {
            throw new RuntimeException("节点已有右子节点,无法添加右子节点");
        }
        TreeNode newNode = new TreeNode(data);
        if (isLeft) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
        return newNode;
    }

    public boolean empty() {
        return root.data == null;
    }

    public TreeNode root() {
        if (empty()) {
            throw new RuntimeException("树为空,无法访问根节点");
        }
        return root;
    }

    public E parent(TreeNode node) {
        return null;
    }

    public E leftChild(TreeNode parent) {
        if (parent == null) {
            throw new RuntimeException(parent + "节点为null");
        }
        return parent.left == null ? null : (E) parent.left.data;
    }

    public E rightChild(TreeNode parent) {
        if (parent == null) {
            throw new RuntimeException(parent + "节点为null");
        }
        return parent.right == null ? null : (E) parent.right.data;
    }

    public int deep() {
        return deep(root);
    }

    private int deep(TreeNode node) {
        if (node == null) {
            return 0;
        }
        if (node.left == null && node.right == null) {
            return 1;
        } else {
            int leftDeep = deep(node.left);
            int rightDeep = deep(node.right);
            int max = leftDeep > rightDeep ? leftDeep : rightDeep;
            return max + 1;
        }
    }

    public static void main(String[] args) {
        TwoLinkBinTree<String> binTree = new TwoLinkBinTree<>("root");
        TwoLinkBinTree.TreeNode tn1 = binTree.addNode(binTree.root(), "第二层左节点", true);
        TwoLinkBinTree.TreeNode tn2 = binTree.addNode(binTree.root(), "第二层右节点", false);
        TwoLinkBinTree.TreeNode tn3 = binTree.addNode(tn2, "第三层左节点", true);
        TwoLinkBinTree.TreeNode tn4 = binTree.addNode(tn2, "第三层右节点", false);
        TwoLinkBinTree.TreeNode tn5 = binTree.addNode(tn3, "第四层左节点", true);
        System.out.println("tn2的左子节点:" + binTree.leftChild(tn2));
        System.out.println("tn2的右子节点:" + binTree.rightChild(tn2));
        System.out.println(binTree.deep());

    }
}

三叉链表存储:每个节点不仅“记住”它的左、右两个子节点,还“记住”它的父节点。

public class ThreeLinkBinTree<E> {
    public static class TreeNode {
        Object data;
        TreeNode left;
        TreeNode right;
        TreeNode parent;

        public TreeNode() {

        }

        public TreeNode(Object data) {
            this.data = data;
        }

        public TreeNode(Object data, TreeNode left, TreeNode right, TreeNode parent) {
            this.data = data;
            this.left = left;
            this.right = right;
            this.parent = parent;
        }
    }

    private TreeNode root;

    public ThreeLinkBinTree() {
        this.root = new TreeNode();
    }

    public ThreeLinkBinTree(E data) {
        this.root = new TreeNode(data);
    }

    public TreeNode addNode(TreeNode parent, E data, boolean isLeft) {
        if (parent == null) {
            throw new RuntimeException("节点为null,无法添加子节点!!!");
        }
        if (isLeft && parent.left != null) {
            throw new RuntimeException("节点已有左子节点,无法添加左子节点");
        }

        if (!isLeft && parent.right != null) {
            throw new RuntimeException("节点已有右子节点,无法添加右子节点");
        }

        TreeNode newNode = new TreeNode(data);

        if (isLeft) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
        newNode.parent = parent;
        return newNode;
    }

    public boolean empty() {
        return root.data == null;
    }

    public TreeNode root() {
        if (empty()) {
            throw new RuntimeException("树为空,无法访问根节点");
        }
        return root;
    }

    public E parent(TreeNode node) {
        if (node == null) {
            throw new RuntimeException(node + "节点为null,无法访问其父节点");
        }
        return (E) node.parent.data;
    }

    public E leftChild(TreeNode parent) {
        if (parent == null) {
            throw new RuntimeException(parent + "节点为null,无法访问子节点");
        }
        return parent.left == null ? null : (E) parent.left.data;
    }

    public E rightChild(TreeNode parent) {
        if (parent == null) {
            throw new RuntimeException(parent + "节点为null,无法访问子节点");
        }
        return parent.right == null ? null : (E) parent.right.data;
    }

    public int deep() {
        return deep(root);
    }

    private int deep(TreeNode node) {
        if (node == null) {
            return 0;
        }

        if (node.left == null && node.right == null) {
            return 1;
        } else {
            int leftDeep = deep(node.left);
            int rightDeep = deep(node.right);
            int max = leftDeep > rightDeep ? leftDeep : rightDeep;
            return max + 1;
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值