一,树的概念
树是一种非顺序数据结构,一种分层数据的抽象模型,它对于存储需要快速查找的数据非常有用,现实生活中最常见的树的例子是家谱,或是公司的组织架构图,如下图:
二,树的术语
- 节点的度(Degree):节点的子树个数
- 树的度:树的所有节点中最大的度数
- 叶节点(Leaf);度为零的节点(也成为叶子节点)
- 父节点(Parent):有子树的节点是其子数根节点的父节点
- 子节点(Child):若A节点是B节点的父节点,则称B节点是A节点的子节点,子节点也称孩子节点
- 兄弟节点(Subling):具有同一父节点的个节点,彼此是兄弟节点
- 路径和路径长度:从节点n1到nk的路径为一个节点顺序n1,n2,...nk,ni是ni+1的父节点,路径所包含的个数为路径的长度
- 节点的层次(Level):规定根节点在一层,其它任一节点的层数是父节点的层数+1
- 树的深度(Depth):树中所有节点中最大层次是这颗树的深度
三,二叉树
1,二叉树的概念:如果树的每一个节点最多只能有两个子节点,这样的树就称为 “二叉树”,任何树都可以转换为二叉树
2,二叉树的定义
- 二叉树可以为空,也就是没有节点
- 若不为空,则它是由根节点和称其为“左子树TL”和“右子树TR”的两个不相交的二叉树组成
3,二叉树的特征
- 一个二叉树第i层最大节点数为:2^(i-1),i>=1
- 深度为k的二叉树最大节点总数为:2的K次方-1,k>=1
- 对任何非空二叉树下,若n0表示节点的个数,n2是度为2的非叶节点个数,那么两者满足关系:n0=n2+1
四,二叉搜索树
1,概念:二叉搜索树(BST,Binary Search Tree),也称为二叉搜索树
2,二叉搜索树的特性
如果树不为空
- 非空左子树的所有键值小于其根节点的键值
- 非空右子树的所有键值大于其根节点的键值
- 左,右子树本身也都是二叉搜索树
3,递归函数的原理(树的操作大部分使用递归)
void dosh(int num)
{
if(num==0)
{
return ;
}
else
{
printf("我要上东华")
dosh(num-1)
}
}
void main()
{
dosh(3)
}
五,二叉搜索树的常见操作
- insert(key):向树中插入一个新的键
- search(key):向树中查找一个键,如果节点存在,则返回true,如果不存在,则返回false
- preOrderTraversal(handler):通过先序遍历方式遍历所有的节点
- midOrderTraversal(handler):通过中序遍历方式遍历所有的节点
- postOrderTraversal(handler):通过后续遍历方式遍历所有的节点
- min():返回树中最小的值
- max():返回树中最大的值
- remove(key):从树中移除某个键
六,二叉搜索树的实现
class Node{
constructor(key){
this.key=key
this.left=null
this.right=null
}
}
class BinarySearchTree{
constructor(){
this.root=null
}
insert(key){
var newNode=new Node(key)
if(this.root==null){
this.root=newNode
}else{
this.insertNode(this.root,newNode)
}
}
insertNode(node,newNode){
if(node.key>newNode.key){
if(node.left==null){
node.left=newNode
}else{
this.insertNode(node.left,newNode)
}
}else if(node.key<newNode.key){
if(node.right==null){
node.right=newNode
}else{
this.insertNode(node.right,newNode)
}
}else{
}
}
preOrderTraversal(handler){
this.preOrderTraversalNode(this.root,handler)
}
preOrderTraversalNode(node,handler){
if(node != null){
handler(node.key)
this.preOrderTraversalNode(node.left,handler)
this.preOrderTraversalNode(node.right,handler)
}
}
midOrderTraversal(handler){
this.midOrderTraversalNode(this.root,handler)
}
midOrderTraversalNode(node,handler){
if(node != null){
this.midOrderTraversalNode(node.left,handler)
handler(node.key)
this.midOrderTraversalNode(node.right,handler)
}
}
postOrderTraversal(handler){
this.postOrderTraversalNode(this.root,handler)
}
postOrderTraversalNode(node,handler){
if(node != null){
this.postOrderTraversalNode(node.left,handler)
this.postOrderTraversalNode(node.right,handler)
handler(node.key)
}
}
max(){
var node=this.root
var key=null
while(node.right !=null){
node=node.right
key=node.key
}
return key
}
min(){
var node=this.root
var key=null
while(node.left !=null){
node=node.left
key=node.key
}
return key
}
search(key){
var node=this.root
while(node !=null){
if(node.key>key){
node=node.left
}else if(node.key<key){
node=node.right
}else{
return true
}
}
return false
}
remove(key){
var current=this.root
var psrent=null
var isLeftChild=true
while(current.key !=key){
parent=current
if(key<current.key){
isLeftChild=true
current=current.left
}else{
isLeftChild=false
current=current.right
}
if(current==null) return false
}
if(current.left==null && current.right==null){
if(current==this.root){
this.root=null
}else if(isLeftChild){
parent.left=null
}else{
parent.right=null
}
}
else if(current.right==null){
if(current==this.root){
this.root=current.left
}else if(isLeftChild){
parent.left=current.left
}else{
parent.right=current.left
}
}else if(current.left==null){
if(current=this.root){
this.root=current.right
}else if(isLeftChild){
parent.left=current.right
}else{
parent.right=current.right
}
}
else{
var successor=this.getSuccessor(current)
if(current==this.root){
this.root=successor
}else if(isLeftChild){
parent.left=successor
}else{
parent.right=successor
}
successor.left=current.left
}
}
getSuccessor(delNode){
var successor=delNode
var current=delNode.right
var successorParent=delNode
while(current !=null){
successorParent=successor
successor=current
current=current.left
}
if(successor != delNode.right){
successorParent.left=successor.right
successor.right=delNode.right
}
return successor
}
}
var bst = new BinarySearchTree()
bst.insert(11)
bst.insert(7)
bst.insert(15)
bst.insert(5)
bst.insert(3)
bst.insert(9)
bst.insert(8)
bst.insert(10)
bst.insert(13)
bst.insert(12)
bst.insert(14)
bst.insert(20)
bst.insert(18)
bst.insert(25)
console.log(bst)
var resultString_one=''
var resultString_two=''
var resultString_three=''
bst.preOrderTraversal(function (key) {
resultString_one += key + " "
})
console.log(resultString_one, "one")
bst.midOrderTraversal(function (key) {
resultString_two += key + " "
})
console.log(resultString_two, "two")
bst.postOrderTraversal(function(key){
resultString_three+=key+" "
})
console.log(resultString_three,"three")
console.log(bst.max(),"max")
console.log(bst.min(),"min")
console.log(bst.search(11))
bst.remove(9)
bst.remove(7)
bst.remove(15)
bst.remove(16)
var resultString_four = ''
bst.preOrderTraversal(function (key) {
resultString_four += key + " "
})
console.log(resultString_four,"four")