树数据结构
树是一种分层抽象模型,现实中常见例子是家谱,或是公司架构图。 位于树顶部的节点叫根节点。,他没有父节点,树中的每个元素都叫做节点,
节点分为内部节点和外部节点 至少有一个子节点的节点称为内部节点。没有子元素的节点称为外部节点或者叶节点。
一个节点可以有祖先和后代。一个节点(除了根节点)的祖先包括父节点。祖父节点,曾祖父节点等,一个节点的后代包括子节点孙节点,曾孙节点等。
子树:子树由节点和他的后代构成。
节点的属性是深度,节点的深度取决于它的祖先节点的数量。
树的高度取决于所有节点神的的最大值,一棵树也可以被分解成层级。根节点在第0层,它的子节点在第一层。以此类推。
二叉树和二叉搜素树
二叉树中的节点最多只能有两个子节点,一个左侧子节点和右侧自节点。
二叉搜索树(BST)是二叉树的一种,但是只允许你在左侧节点存储(比父节点)小的值,在右侧节点存储(比父节点)大的值。
创建BinarySearchTree类
export class Node{
consutructor(key){
this.key=key
this.left=null
this.right=null
}
}
和链表一样,我们将通过指针引用来表示节点之间的关系。在双向链表中,每个节点包含两个指针,一个指针指向下一个节点,,另一个指向上一个节点对于树,使用相同的方式,但是一个指向左侧节点,另一个指向右侧节点。因此,将声明一个Node类来表示树的每个节点,键是树相关的术语中对节点的称呼。
export default class BinarySearchTree{
consutructor(compareFn=defCompare){
this.compareFn=compareFn//用来比较节点值
this.root=null
}
}
root和链表中的head模式相同
insert(key):向树中插入一个新的键
search(key):在树中查找一个键。如果节点存在,则返回true,反之false
inOrderTraverse():通过中序遍历方式遍历所有节点
preOrderTraverse():通过先序遍历方式遍历所有节点
postOrderTraverse():通过后序遍历方式遍历所有节点
min():返回树中最小的值/键
max():返回树中最大的值/键
remove():从树中移除某个键
向二叉搜索树中插入一个键
insert(key){
if(this.root=null){
this.root=new Node(key)
}else{
this.insertNode(this.root,key)
}
}
要向树中插入一个节点要三个步骤
第一步验证插入操作是否是特殊情况。对于二叉搜索树的特殊情况是,我们尝试插入的树节点是否为第一个节点,是,我们要做的是创建一个Node类的实例并将它赋值给root属性来讲root指向这个新节点。因为在Node构建函数的属性里只需要向构造函数传递我们想用来插入树的节点值key,他的左指针和右指针的值会由构造函数自动设置为null.
第二步是将节点添加到根节点以外的其他位置。我们需要一个辅助方法
insertNode(node,key){
if(this.compareFn(key,node.key)===CompoareLESS_THAN){
if(node.left==null){
node.left=new Node(key)
}else{
this.insertNode(node.left,key)
}
}else{
if(node.right==null){
node.right=new Node(key)
}else{
this.insertNode(node.right,key)
}
}
}
insertNode方法会帮助我们找到新节点应该插入的正确位置,实现步骤
如果树非空,需要找到插入新节点的位置。因此在调用insertNode方法时要通过参数传入树的根节点和要插入的节点
如果新节点的键小于当前节点的键(现在当前节点就是根节点)那么需要检查当前节点的左侧子节点,注意,由于键可能是负载的对象而不是数,我们使用传入二叉搜索构造函数的compareFn函数来比较值。如果他没有左侧子节点,就在左侧插入新节点,如果有左子节点,需要通过递归insertNode方法继续找到树的下一层。在这里,下次要比较的节点将会是当前节点的左侧子节点(左侧节点子树)
未完待续。。。