樹結構——javascript實現刪除及其他方法

非線性結構

樹的術語:

節點的度——節點的子樹點個數

樹的度——樹的所有節點中最大的度數

任何一顆樹最後都可以用二叉樹(每個節點的子節點最多隻有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>

刪除方法

 

紅黑樹詳解:https://www.jianshu.com/p/00aae4f4d672

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章