【数据结构&算法】二叉树的概念和多种遍历方式

树系列:

一、前言

最近在深入了解MySQL索引,发现MySQL索引主要用B+树实现的。本人对树这种数据结构,一直以来掌握都是模棱两可的状态,现在希望通过写一个关于树的专题系列,来掌握树这种数据结构,为深入了解MySQL索引打下基础,做到心中有"树"。

二、二叉树理论篇

二叉树的定义

二叉树(Binary Tree) 是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的,分别称为根结点的左子树和右子树组成。
通俗的说:每个结点的度均不超过2的有序树,称为二叉树
在这里插入图片描述

二叉树的分类

根据结点分布的不同可将二叉树分为:满二叉树、完全二叉树、斜树

满二叉树

在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
在这里插入图片描述
特点:

  • 叶子只能出现在最下一层
  • 非叶子结点的度一定是2
完全二叉树

对一颗具有n个结点的二叉树按层编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。
在这里插入图片描述
特点:

  • 叶子结点只能出现在最下层和倒数第二层。
  • 最下层的叶子结点集中在树的左部。
  • 倒数第二层若存在叶子结点,一定在右部连续位置。
    注:满二叉树一定是完全二叉树,但反过来不一定成立。
斜树

斜树是特殊的二叉树,所有结点都只有左子树的二叉树左斜树,反之叫右斜树,统称为斜树。
斜树的特点所有结点都在一个方向,更像是数组或链表,已经失去了二叉树的优势,所以在实际的开发应用中尽量避免斜树的出现。
在这里插入图片描述

二叉树的存储结构
顺序存储

对于满二叉树和完全二叉树来说,可以将结点逐层的放到一组连续的存储空间里,一维数组就比较适合,并且结点的存储位置就是数组的下标索引。
在这里插入图片描述
完全二叉树的顺序存储
在这里插入图片描述
可以看出,刚好填满整个数组下标和完全二叉树的结点一一对应,不浪费存储空间。
对于一般二叉树来说,需要用虚拟结点来补充成一颗完全二叉树来存储,否则无法确定结点间的关系,这样的话会造成空间的浪费。
极端情况需要补充很多结点,比如斜树
在这里插入图片描述
在这里插入图片描述

链式存储

既然顺序存储对完全二叉树和满树比较适用,一般的二叉树我们可以考虑用链式存储结构。二叉树中每个结点最多有二个孩子结点,因此可以设计成:数据域加左右孩子域,左右孩子域分别存放左右子树的引用
在这里插入图片描述在这里插入图片描述
采用一种链表结构存储二叉树,二叉链表

三、实现篇

前面讲了二叉树的一些概念,下面讲解代码实现
在这里插入图片描述

类结构
public class BinTree {
    Node root;
    private static class Node {
        private String data;
        private Node left;
        private Node right;

        public Node(String data) {
            this.data = data;
        }
        @Override
        public String toString() {
            return "Node{" +
                    "data='" + data + '\'' +
                    '}';
        }
    }
}
创建二叉树
public void createTree(String[] dataList) {
        List<Node> nodeList = new ArrayList<>();
        for (String item : dataList) {
            Node node = new Node(item);
            nodeList.add(node);
        }
        this.root = nodeList.get(0);
        for (int i = 0; i < nodeList.size() / 2; i++) {
            nodeList.get(i).left = nodeList.get(i * 2 + 1);
            int index = i * 2 + 2;
            if (index < nodeList.size()) {//防止集合越界
                nodeList.get(i).right = nodeList.get(index);
            }
        }
    }
前序遍历

根结点->左子树->右子树

    public void preOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println(node);
        preOrder(node.left);
        preOrder(node.right);
    }

结果:ABDECGH

中序遍历

左子树->根结点->右子树

  public void inOrder(Node node){
      if (node == null) {
          return;
      }
      inOrder(node.left);
      System.out.println(node);
      inOrder(node.right);
  }

结果:DBEAGCH

后序遍历

左子树->右子树->根结点

  public void postOrder(Node node){
      if (node == null) {
          return;
      }
      postOrder(node.left);
      postOrder(node.right);
      System.out.println(node);
  }

结果:DEBGHCA

四 完整代码

public class BinTree {
    Node root;
    private static class Node {
        private String data;
        private Node left;
        private Node right;

        public Node(String data) {
            this.data = data;
        }
        @Override
        public String toString() {
            return "Node{" +
                    "data='" + data + '\'' +
                    '}';
        }
    }

    public void createTree(String[] dataList) {
        List<Node> nodeList = new ArrayList<>();
        for (String item : dataList) {
            Node node = new Node(item);
            nodeList.add(node);
        }
        this.root = nodeList.get(0);

        for (int i = 0; i < nodeList.size() / 2; i++) {

            nodeList.get(i).left = nodeList.get(i * 2 + 1);
            int index = i * 2 + 2;
            if (index < nodeList.size()) {//防止集合越界
                nodeList.get(i).right = nodeList.get(index);
            }
        }

    }

    /**
     * 前序遍历
     * @param node
     */
    public void preOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println(node);
        preOrder(node.left);
        preOrder(node.right);
    }

    /**
     * 中序遍历
     * @param node
     */
  public void inOrder(Node node){
      if (node == null) {
          return;
      }
      inOrder(node.left);
      System.out.println(node);
      inOrder(node.right);
  }

    /**
     * 后序遍历
     * @param node
     */
  public void postOrder(Node node){
      if (node == null) {
          return;
      }
      postOrder(node.left);
      postOrder(node.right);
      System.out.println(node);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值