非線性結構
樹的術語:
節點的度——節點的子樹點個數
樹的度——樹的所有節點中最大的度數
任何一顆樹最後都可以用二叉樹(每個節點的子節點最多隻有2個)模擬
二叉搜索樹(BST, Binary Search Tree),又稱爲二叉排序樹或二叉找樹
查找效率高
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>樹結構</title>
</head>
<body>
<script>
//封裝二叉搜索樹
function BinarySearchTree(){
function Node(key){
this.key = key
this.left = null
this.right = null
}
//屬性
this.root = null
//方法
BinarySearchTree.prototype.insert = function(key){
var newNode = new Node(key)
if(this.root === null){
this.root = newNode
}else{
this.insertNode(this.root, newNode)
}
}
//利用遞歸方法插入數據
BinarySearchTree.prototype.insertNode = function(node,newNode){
if(newNode.key < node.key){//向左查找
if(node.left ==null){
node.left = newNode
}else{
this.insertNode(node.left,newNode)
}
}else{
if(node.right ==null){
node.right = newNode
}else{
this.insertNode(node.right,newNode)
}
}
}
//樹的遍歷
//1.先序遍歷
BinarySearchTree.prototype.preOrderTraversal = function(hander){
this.preOrderTraversalNode(this.root,hander)
}
//2.遞歸遍歷子節點
BinarySearchTree.prototype.preOrderTraversalNode = function(node, hander){
if(node!=null){
//2.1 獲得當前值
hander(node.key)
//2.2 遍歷左側的子節點樹
this.preOrderTraversalNode(node.left,hander)
//2.3 遍歷右側的子節點樹
this.preOrderTraversalNode(node.right,hander)
}
}
//搜索特定的key
BinarySearchTree.prototype.search = function(key){
var node = this.root
while(node!=null){
if(key < node.key){
node = node.left
}else if(key > node.key){
node = node.right
}else{
return true
}
}
return false
}
//樹的最大值
BinarySearchTree.prototype.max = function(){
//1.獲取根節點
var node = this.root
//2.向右查找,直到node爲null
var key = null
while(node!=null){
key = node.key
node = node.right
}
return key
}
//樹的最小值
BinarySearchTree.prototype.min = function(){
var node = this.root
while(node.left!=null){
node = node.left
}
return node.key
}
BinarySearchTree.prototype.remove = function(key){
//1.尋找要刪除的節點
//1.1 定義變量,記錄找到的節點及位置
var current = this.root
var parent = null
var isLeftNode = null
//1.2 開始尋找要刪除的節點
while(current.key != key){
parent = current
if(key < current.key){
isLeftNode = true
current = current.left
}else{
isLeftNode = false
current = current.right
}
//current已經指向了null,說明沒有找到需要刪除的key
if(current == null){
return false
}
}
//2.根據不同的情況刪除節點
//找到了current.key ==key
//2.1 刪除葉子節點(沒有子節點的節點)
if(current.right ==null && current.left == null){
if(parent===this.root){
this.root = null
}else if(isLeftNode){
parent.left = null
}else{
parent.right = null
}
}else if(current.right === null){
//2.2 刪除只有一個節點的節點
if(current == this.root){
this.root = current.left
}else if(isLeftNode){
parent.left = current.left
}else{
parent.right = current.left
}
}else if(current.left === null){
if(current == this.root){
this.root = current.right
}else if(isLeftNode){
parent.left = current.right
}else{
parent.right = current.right
}
}else{//2.3 刪除有兩個節點的節點
//1.獲得後繼節點
var successor = this.getSuccessor(current)
//2.判斷是否爲根節點,並用後繼節點代替 刪除節點 位置
if(current === this.root){
this.root = successor
}else if(isLeftNode){
parent.left = successor
}else{
parent.right = successor
}
//3.將刪除節點的左子樹賦值給 後繼節點;
successor.left = current.left
}
return true
}
//找後繼的方法
BinarySearchTree.prototype.getSuccessor = function(delNode){
//1.定義變量,記錄找到的後繼
var successor = delNode
var current = successor
var parentSuccessor = current
//2.循環查找右子樹上的最小值,即找到current.left==null
while(current!=null){
parentSuccessor = successor
successor= current
current = current.left
}
//3.判斷後繼是否是delNode的right節點
//不是的話,將後繼的右節點賦值給後繼的父節點:後繼的父節點.left = 後繼.right;
//將刪除節點的右子樹賦值給 後繼節點:後繼.right = delNode.right
if(successor!= delNode.right){
parentSuccessor.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)
bst.insert(6)
//測試先序遍歷
var resultString =''
bst.preOrderTraversal(function(key){
resultString +=key + ' '
})
alert(resultString)
// alert('max:'+bst.max())
// alert(bst.min())
//
// alert(bst.search(13))
// alert(bst.search(1))
bst.remove(9)
bst.remove(7)
bst.remove(15)
var resultString =''
bst.preOrderTraversal(function(key){
resultString +=key + ' '
})
alert(resultString)
</script>
</body>
</html>
刪除方法