心里有点树 (一)

简介: 心里有点树 (一)

why 树#


  • 顺序存储


顺序存储的特点是各个存储单位在逻辑和物理内存上都是相邻的,典型的就是代表就是数组,物理地址相邻因此我们可以通过下标很快的检索出一个元素。

我们想往数组中添加一个元素最快的方式就是往它的尾部添加。如果往头部添加元素的话效率就很低,因为需要将从第一个元素开始依次往后移动一位,这样就能空出第一位的元素,然后才能将我们指定的数据插入到第一个的位置上。


  • 链式存储


链式存储的特点是:各个节点之间逻辑是相邻的,但是物理存储上不相邻,每一个节点都存放一个指针或者是引用用来指向它的前驱或者后继节点, 因此我们想插入或者删除一个元素时速度就会很块,只需要变动一下指针的指向就行。

但是对链表来说查找是比较慢的,因为对任意一个节点来说,它只知道自己的下一个节点或者是上一个节点在哪里。因此每次查找都需要从头结点开始遍历...



树型存储结构有很多种。比如什么二叉树、满二叉树、B树、B+树、红黑树等,对于树形结构来说,它会相对中和链式存储结构和顺序存储结构的优缺点 (其中二叉排序树最能直接的体现出树中和链式存储和线性存储的特性,下文有说)


树的概述#



如上图是一个二叉树,当然树还能有三叉,四叉等,对树来说它们有如下的诸多属性。

  • 根节点: 最顶上的节点 即a
  • 层: 根节点在第一层 BE在第二层
  • 高度: 最大的层数
  • 森林: 多个树的组合
  • 权: 节点上的值 如根节点的权是 a
  • 叶子节点: 下层上的节点是上一层的叶子节点
  • 双亲节点: 上层的节点是下层的节点的双亲节点(单个节点又是爸又是妈)
  • 路径: 找到C的路径是 a-b-c
  • 度: 就是直接子节点的个数


普通二叉树#


  • 什么是二叉树?



顾名思义就是度最大为2的树就是二叉树。而且对二叉树来说是严格区分左子树和右子树的。看上图,虽然两个树的根节点都是1,但是它们的左右子树不同,因此它们并不是相同的树。


  • 什么是满二叉树?



像上图这样所有的叶子节点都在最后一层,除了最后一层之外其他层的节点都有两个子节点。

二叉树的全部节点计算公式是2^n-1 , n是层数


  • 什么是完全二叉树?



像上图这样,所有的叶子点都在最后一层或者是倒数第二层,并且从左往右数是连续的。


java&二叉树#


  • 封装二叉树节点


public class TreeNode {
    // 权
    private int value;
    // 左节点
    private TreeNode leftNode;
    // 右节点
    private TreeNode rightNode;
}


  • 封装二叉树


public class BinaryTree {
    TreeNode root;
    public void setRoot(TreeNode root) {
        this.root = root;
    }
    public TreeNode getRoot() {
        return this.getRoot();
    }
}


遍历#



像这样一颗二叉树,通过不同的顺序遍历会得到不同的结果。

前中后的顺序说的是root节点的顺序,前序的话就是先遍历父节点,中序就是左父右 后续就是左右父。


  • 前序遍历


public void frontShow() {
        System.out.println(this.value);
        if (leftNode != null)
            leftNode.frontShow();
        if (rightNode != null)
            rightNode.frontShow();
    }


  • 中序遍历


public void middleShow() {
        if (leftNode != null)
            leftNode.middleShow();
        System.out.println(value);
        if (rightNode != null)
            rightNode.middleShow();
    }


  • 后续遍历


public void backShow() {
        if (leftNode != null)
            leftNode.backShow();
        if (rightNode != null)
            rightNode.backShow();
        System.out.println(value);
    }


查找#


其实有了上面三种遍历的方式,查找自然存在三种,一边遍历一边查找。


public TreeNode frontSeach(int num) {
        TreeNode node = null;
        // 当前节点不为空,返回当前节点
        if (num == this.value) {
            return this;
        } else {
            // 查找左节点
            if (leftNode != null) {
                node = leftNode.frontSeach(num);
            }
            if (node != null)
                return node;
            // 查找右节点
            if (rightNode != null)
                node = rightNode.frontSeach(num);
        }
        return node;
    }


删除节点#


删除节点也是,不考虑特别复杂的情况,删除节点就有两种情况:第一种要删除的节点就是根节点,那么让根节点=null就ok。第二种情况要删除的节点不是根节点,就处理它的左右节点,左右节点还不是需要删除的元素的话那么就得递归循环这个过程。


// 先判断是否是根节点,在调用如下方法
   public void deleteNode(int i) {
        TreeNode parent = this;
        // 处理左树
        if (parent.leftNode!=null&&parent.leftNode.value==i){
            parent.leftNode=null;
            return;
        }
        // 处理左树
        if (parent.rightNode!=null&&parent.rightNode.value==i){
            parent.rightNode=null;
            return;
        }
        // 递归-重置父节点
        parent=leftNode;
        if (parent!=null)
            parent.deleteNode(i);
    // 递归-重置父节点
        parent=rightNode;
        if (parent!=null)
            parent.deleteNode(i);
    }


顺序存储二叉树#


文章一开始刚说了,顺序存储的数据结构的典型代表就是数组,如下:


[1,2,3,4,5,6,7]


什么是顺序存储的二叉树呢? 其实就是将上面的数组看成了一颗树,就像下图这样



数组转换成二叉树是有规律的,这个规律就体现在它们的下标的关联上,比如我们想找2节点的左子节点的下标就是 2*n -1 = 3 , 于是我们从数组中下标为3的位置取出4来

  • 第n个元素的左子节点是 2n-1
  • 第n个元素的右子节点是 2n-2
  • 第n个元素的父节点是 (n-1)/2
  • 遍历顺序存储的二叉树


public void frontShow(int start){
        if (data==null||data.length==0){
            return;
        }
        // 遍历当前节点
        System.out.println(data[start]);
        // 遍历左树
        if (2*start+1<data.length)
            frontShow(2*start+1);
        // 遍历右树
        if (2*start+2<data.length)
            frontShow(2*start+2);
    }




相关文章
|
5月前
|
存储
第7章 神奇的树
第7章 神奇的树
|
6月前
|
存储 算法 Unix
简单介绍一些其他的树
简单介绍一些其他的树
|
存储 缓存 关系型数据库
B树与B+树
B树与B+树
52 0
B树与B+树
|
存储 缓存 算法
B树,B-树,B+树和B*树
B树,B-树,B+树和B*树
系统发育树初步剖析
1. 什么是系统发育树 2. 如何看系统发育树并确定哪些物种最相关
207 0
|
存储 关系型数据库 MySQL
B树和B+树的理解
B树和B+树的理解
B树和B+树的理解
|
存储
你说什么是树?
你说什么是树?
117 0
你说什么是树?
|
Java 容器
心里有点树 (二)
心里有点树 (二)
109 0
|
存储
心里有点树 (三)
心里有点树 (三)
149 0
|
存储 数据库 索引
B树和B+树
本文转载自博客,因为题主写的已经很详细了。 还有,必须要强调一点,树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下,只有减少树的深度,让树从“高瘦”变成“矮胖”就可以减少I/O次数,从而提高查询效率(查找树的每一个结点都要进行一次I/O) B树是为实现高效的磁盘存取而设计的多叉平衡搜索树。
2102 0