数据结构-树


一、树的概念

有很多数据的逻辑关系并不是线性关系,在实际场景中,常常存在着一对多,甚至是多对多的情况,它是由n(n≥0)个有限节点组成一个具有层次关系的集合

img

树的分类如下:

image-20220417232819289

二、二叉树

二叉树(binary tree)是树的一种特殊形式。二叉,顾名思义,这种树的每个节点最多有2个孩子节 点。注意,这里是最多有2个,也可能只有1个,或者没有孩子节点。

image-20220417232900753

二叉树节点的两个孩子节点,一个被称为左孩子(left child),一个被称为右孩子(right child)。这 两个孩子节点的顺序是固定的,左孩子小于右孩子。

满二叉树

一个二叉树的所有非叶子节点都存在左右孩子,并且所有叶子节点都在同一层级上,那么这个树就
是满二叉树

image-20220417233003633

完全二叉树

对一个有n个节点的二叉树,按层级顺序编号,则所有节点的编号为从1到n。如果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同,则这个二叉树为完全二叉树

image-20220417233042864

满二叉树要求所有分支都是满的;而完全二叉树只需保证最后一个节点之前的节点都齐全即可

二叉树的存储

二叉树属于逻辑结构,可以使用链表和数组进行存储。

链式存储

image-20220417234401232

  • 二叉树的每一个节点包含3部分
    • 存储数据的data变量
    • 指向左孩子的left指针
    • 指向右孩子的right指针

数组存储

使用数组存储时,会按照层级顺序把二叉树的节点放到数组中对应的位置上。如果某一个节点的左孩子或右孩子空缺,则数组的相应位置也空出来

image-20220417233247001

寻址方式:

一个父节点的下标是n,那么它的左孩子节点下标就是2×n+1、右孩子节点下标就是2*(n+1) 对于一个稀疏的二叉树(孩子不满)来说,用数组表示法是非常浪费空间的 所以二叉树一般用链表存储实现。(二叉堆除外)

二叉查找树

二叉查找树(binary search tree),二叉查找树在二叉树的基础上增加了以下几个条件

如果左子树不为空,则左子树上所有节点的值均小于根节点的值

如果右子树不为空,则右子树上所有节点的值均大于根节点的值

左、右子树也都是二叉查找树

image-20220417233405576

二叉查找树要》 求左子树小于父节点,右子树大于父节点,正是这样保证了二叉树的有序性。因此二叉查找树还有另一个名字——二叉排序树(binary sort tree)

三、二叉树的遍历

二叉树,是典型的非线性数据结构,遍历时需要把非线性关联的节点转化成一个线性的序列,以不同的
方式来遍历,遍历出的序列顺序也不同

3.1 深度优先遍历

所谓深度优先,顾名思义,就是偏向于纵深,“一头扎到底”的访问方式

前序遍历

二叉树的前序遍历,输出顺序是根节点、左子树、右子树

中序遍历

二叉树的中序遍历,输出顺序是左子树、根节点、右子树

后序遍历

二叉树的后序遍历,输出顺序是左子树、右子树、根节点

四、代码实现

public class TreeNode {

    public int data; // 数据节点

    public TreeNode leftChild; // 左孩子
    public TreeNode rightChild; // 右孩子


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



/**
 * 二叉查找树
 */
public class BinarySearchTreeNode {


    private TreeNode root; // 根节点

    public void insertNode(int data) {
        root = insertNode(root, data);
    }


    /**
     *
     * @param node 当前数的根节点
     * @param data
     */
    public TreeNode insertNode(TreeNode node, int data) {
        if (null == node) {
            return new TreeNode(data);
        }


        if (data < node.data) {
            node.leftChild = insertNode(node.leftChild, data);
        } else if (data > node.data) {
            node.rightChild = insertNode(node.rightChild, data);
        } else{
            node.data = data;
        }
        return node;
    }


    /**
     * 前序遍历 根 左 右
     * @param node
     */
    public static void preorderTraversal(TreeNode node) {
        // 终止条件
        if (null == node) {
            return;
        }
        System.out.println(node.data);
        preorderTraversal(node.leftChild);
        preorderTraversal(node.rightChild);
    }


    /**
     * 中序遍历 左 根 右
     * @param node
     */
    public static void inorderTraversal(TreeNode node) {
        // 终止条件
        if (null == node) {
            return;
        }

        inorderTraversal(node.leftChild);
        System.out.println(node.data);
        inorderTraversal(node.rightChild);
    }

    /**
     * 前序遍历 左 根 右
     * @param node
     */
    public static void postorderTraversal(TreeNode node) {
        // 终止条件
        if (null == node) {
            return;
        }
        postorderTraversal(node.leftChild);
        postorderTraversal(node.rightChild);
        System.out.println(node.data);
    }

    /**
     *                 ┌───┐
     *                 │ 10│
     *           ┌─────┴───┴───┐
     *           │             │
     *         ┌─┴─┐          ┌┴───┐
     *         │  8│          │  11│
     *      ┌──┴───┴──┐       └────┴────┐
     *      │         │                 │
     *   ┌──┴┐      ┌─┴─┐             ┌─┴──┐
     *   │ 7 │      │ 9 │             │12  │
     *   └───┘      └───┘             └────┘
     * @param args
     */

    public static void main(String[] args) {
        // 构建一个二叉查找树
        BinarySearchTreeNode btt= new BinarySearchTreeNode();
        btt.insertNode(10);
        btt.insertNode(8);
        btt.insertNode(11);
        btt.insertNode(7);
        btt.insertNode(9);
        btt.insertNode(12);

        // 前序遍历
        preorderTraversal(btt.root);
        System.out.println("---------------------------");
        inorderTraversal(btt.root);
        System.out.println("---------------------------");
        postorderTraversal(btt.root);

    }



}

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/245503.html

(0)
上一篇 2022年4月18日 11:27
下一篇 2022年4月18日 11:28

相关推荐

发表回复

登录后才能评论