1.树结构
- 真实的树:
相信每个人对现实生活中的树都会非常熟悉。 - 让我们来看一下树有什么特点?
树通常下面有一个根,连接着根的是树干。
树干上面会进行分叉成树枝,数值还会分查成更小的树枝。
在树枝的最后是叶子。 - 树的抽象:
专家们对树的结构进行了抽象,发现树可以模拟生活中很多的场景。
2.生活场景
-
公司的组织架构
-
家谱
3.树结构的抽象
- 将树结构抽象出来就是我们要学习的树结构。
4.树的优点
我们之前已经学习了多种数据结构来爆粗拿数据,为什么我们要使用树结构来保存数据呢?
- 优点:
- 我们不能说树结构比其他数据结构都好。因为每种数据结构都有自己的应用场景。
- 当然树结构也综合了上面的优点
- 树结构可以表示一对多的关系,不是线性结构
树结构和数组,链表,哈希表对比有什么优点呢?
数组:
-
优点
- 数组的主要优点是可以根据下标来查找,访问效率高。
- 但是如果根据数据来查找就会变得复杂。
- 比较好的方式是先对数组进行排序,再进行二分查找。
-
缺点
- 需要对数组进行排序,生成有序数组,才能提高查找效率。
- 在数组中插入和删除元素,需要有大量的唯一操作。
链表:
- 优点
- 链表的插入和删除操作效率都很高。
- 缺点
- 查找效率很低,需要从头开始依次访问链表中的每个数据,直到找到。
- 而且即时插入和删除操作效率很高,但是如果要插入和删除中间位置的数据,还是需要从头先找到对应的数据。
哈希表:
- 优点
- 我们学过哈希表后,发现哈希表的插入/查询/删除效率都是很高的
- 但是哈希表也有很多缺点
- 缺点
- 空间利用率不高,底层使用的是数组,并且某些单元是没有被利用的。
- 不能啊按照固定的顺序来遍历哈希表中的元素
- 不能快速找到哈希表中的最大值,最小值或者特殊的值。
5.树结构的术语
在描述树的时候有许多术语
- 树(Tree):n(n >= 0)个节点公朴成的有限集合
n = 0时,称为空树。 - 对于任意一个非空树(n > 0),他具备以下性质
- 树中有一份称为根的特殊节点,用r表示
- 其余节点可分为m(m > 0)个互不相交的有限集T1,T2。。。每个集合本身又是一棵树,称为原来树的子树。
- 节点的度:节点的子树个数。
- 树的度:树的所有节点中最大的度数。
- 叶子节点:度为0的节点,也就是叶子节点。
- 父节点:有子树的节点,是其子树的根节点的父节点
- 子节点:A为B节点的父节点,B为A的子节点
- 兄弟节点:同一个父节点的子节点
- 路径和路径长度:包含边的个数
- 节点层次: 根节点所在层次为1,依次2,3,4,5
- 树的深度:书中所有节点中的最大层次
6.用代码的方式模拟树
- 普通表示法
- 儿子-兄弟表示法
7.二叉树的概念
如果树中每个系欸但最多只能额有两个子节点,这样的树就成为"二叉树"
前面,我们已经提到过二叉树的重要性,不仅仅是因为简单,也因为几乎所有的树都可以表示成二叉树的形式
二叉树的定义
- 二叉树可以为空,也就是可以没有节点
- 如哦不为空,则它是由根节点和称其为左子树和右子树的两个不相交的二叉树组成。
- 二叉树有五种形态
二叉树的特性
- 一个二叉树第i层的最大节点数为:2^(i-1),i >= 1
- 深度为k的二叉树有最大节点数为: 2^k - 1, k >= 1;
- 对任何非空二叉树T,若n0表示叶节点的个数,n2是度为2的非叶节点的个数,满足n0 = n2 + 1;
8.二叉树的存储
-
数组
-
链表
二叉树最常见的方式还是使用链表存储。
每个节点封装成一个Node,Node中包含存储的数据,左节点的引用,右节点的引用。
9.什么是二叉搜索树?
- 二叉搜索树(BST)[Binary Search Tree]:又被称为二叉排序树或者二叉查找树。
- 二叉搜索树是一颗二叉树,可以为空:
- 如果不为空,满足以下性质。
- 非空左子树的所有键值小于其根节点的键值。
- 非空右子树的所有键值大于其根节点的键值。
- 左右子树本身也都是二叉搜索树。
- 二叉搜索树的特点:
- 二叉树的特点就是相对较小的值总是保存在左节点上,相对较大的值总是保存在右节点上。
- 那么利用这个特点,我们可以做什么事情呢?
- 查找效率非常高,这也是二叉搜索树中,搜索的来源。
- 二叉搜索树的好处
- 这种查找元素的方式就是二分查找的方式
- 查找所需的最大次数等于二叉树的深度
- 插入结点的时候,也利用类似的方法,一层层的比较大小,找到新节点合适的位置。
10.二叉搜索树的封装
- 我们像封装其他数据结构一样,封装一个BinarySearchTree的类
image
//二叉搜索树的封装
function BinarySearchTree(){
//属性
this.root = null;
//内部类
function Node(key){
this.key = key;
this.left = null;
this.right = null;
}
//方法
}
11.二叉搜索树的常用方法
- 二叉搜索树递归方法的封装
//给用户调用的方法递归方法
//传入被比较的node和要插入的newNode
BinarySearchTree.prototype.insertNode = function(node, newNode){
if(newNode.key < node.key){
//向左查找,又有两种情况
//如果node没有左节点
if(node.left == null){
node.left = newNode;
} else{
//如果node有左节点,递归调用
this.insertNode(node.left, newNode);
}
} else{
//向右查找,也有两种情况 >=
if(node.right == null){
node.right = newNode;
} else{
this.insertNode(node.right, newNode);
}
}
}
- insert(key):插入一个新的键
插入数据代码解析:
BinarySearchTree.prototype.insert = function(key){
//1.根据我们传入的key创建节点
var newNode = new Node(key);
//2.判断根节点是否有值
if(this.root == null){
this.root = newNode;
} else{
//第一次和根节点比较
this.insertNode(this.root, newNode);
}
}
- search(key):查找一个键,有的话返回true,没有返回false
- inOrderTarverse:中序遍历
- preOrderTraverse:先序遍历
- postOrderTraverse:后序遍历
- min:返回树中最小的值
- max:返回最大值
- remove(key): 删除某个值
未完待续。。。。。。