JavaScript树结构——二叉搜索树

JavaScript树结构——二叉搜索树

//二叉搜索树类
function BinarySearchTree(){
	//节点类
	function Node(key, value=key){
		this.key = key
		this.value = value
		this.left = null
		this.right = null
	}
	//根节点
	this.root = null
	/*
	* 1.1 插入或修改数据
	*/ 
	BinarySearchTree.prototype.insert = function(key, value=key){
		let newNode = new Node(key, value=key)
		if (this.root == null){
			this.root = newNode
		}
		else{
			this.insertNode(this.root , newNode)
		}
	}
	/*
	* 1.2 插入数据内置方法
	* 从根节点开始寻找新节点要插入的位置(递归查找合适的空子节点)
	* 参数1:当前节点(初始为根节点) , 参数2:要插入的新节点
	*/ 
	BinarySearchTree.prototype.insertNode = function(node, newNode){
		// 1. 向当前节点左边插入的情况
		if (newNode.key < node.key){
			// 1.1 当前节点的左子节点为空(结束递归)
			if (node.left == null){
				node.left = newNode 
			}
			// 1.2 当前节点的左子节点不为空(继续递归查找)
			else{
				this.insertNode(node.left, newNode)
			}
		}
		// 2. 向当前节点右边插入的情况
		else if (newNode.key > node.key){
			// 2.1 当前节点的右子节点为空(结束递归)
			if (node.right == null){
				node.right = newNode
			}
			// 2.2 当前节点的左子节点不为空(继续递归查找)
			else {
				this.insertNode(node.right, newNode)
			}
		}
		// 3. 修改数据的情况(newNode.key == node.key)
		else{
			node.value = newNode.value
		}
	}
	/*
	* 2.1 先序遍历
	*/ 
	BinarySearchTree.prototype.preOrderTraversal = function(){
		let result = ''
		this.preOrderTraversalNode(this.root, function(key, value){
			result += `${key} => ${value}\n`
		}) 
		return result
	}
	/*
	* 2.2 先序遍历内置方法
	*/ 
	BinarySearchTree.prototype.preOrderTraversalNode = function(node, callback){
		if (node != null){
			//处理数据
			callback(node.key,node.value)
			this.preOrderTraversalNode(node.left, callback)
			this.preOrderTraversalNode(node.right, callback)
		}
	}
	/*
	* 3.1 中序遍历
	*/ 
	BinarySearchTree.prototype.midOrderTraversal = function(){
		let result = ''
		this.midOrderTraversalNode(this.root, function(key, value){
			result += `${key} => ${value}\n`
		})
		return result
	}
	/*
	* 3.2 中序遍历内置方法
	*/ 
	BinarySearchTree.prototype.midOrderTraversalNode = function(node, callback){
		if (node != null){
			this.midOrderTraversalNode(node.left, callback)
			//处理数据
			callback(node.key, node.value)
			this.midOrderTraversalNode(node.right, callback)
		}
	}
	/*
	* 4.1 后序遍历
	*/ 
	BinarySearchTree.prototype.postOrderTraversal = function(){
		let result = ''
		this.postOrderTraversalNode(this.root, function(key, value){
			result += `${key} => ${value}\n`
		})
		return result
	}
	/*
	* 4.2 后序遍历内置方法
	*/ 
	BinarySearchTree.prototype.postOrderTraversalNode = function(node, callback){
		if (node != null){
			this.postOrderTraversalNode(node.left)
			this.postOrderTraversalNode(node.right)
			//处理数据
			callback(node.key, node.value)
		}
	}
	/*
	* 5. 获取key的最值
	*/ 
	BinarySearchTree.prototype.max = function(){
		let node = this.root
		let key = null
		while (node != null){
			key = node.key
			node = node.right
		}
		return key
	}
	BinarySearchTree.prototype.min = function(){
		let node = this.root
		let key = null
		while (node != null){
			key = node.key
			node = node.left
		}
		return key
	}
	/*
	*	6. 查找节点数据
	*/ 
	BinarySearchTree.prototype.search = function(key){
		let node = this.root
		while (node != null){
			if (key < node.key){
				node = node.left
			}
			else if (key > node.key){
				node = node.right
			}
			else {
				return node.value
			}
		}
		return null
	}
	/*
	* 7. 删除节点
	*/ 
	BinarySearchTree.prototype.remove = function(key){
		//定义变量保存信息
		let current = this.root
		let parent = null
		let isLeftChild = true
		//循环查找传入的key
		while (current.key != key){
			parent = current
			
			if (key < current.key){
				isLeftChild = true
				current = current.left
			}
			else{
				isLeftChild = false
				current = current.right
			}
			//找不到返回false
			if (current == null){
				return false
			}
		}
		//循环结束,说明已经找到key所在的节点current和其父节点parent
		// 1. 删除的是叶子节点(没有子节点)
		if (current.left == null && current.right == null){
			// 1.1 删除的是根节点
			if (current == this.root){
				this.root = null
			}
			// 1.2 删除的不是根节点
			else {
				// 删除的是左叶子节点
				if (isLeftChild){
					parent.left = null
				}
				else {
					parent.right = null
				}
			}
		}
		// 2. 删除的节点仅有一个右子节点
		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
			}
		}
		// 3. 删除的节点仅有一个左子节点
		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
			}
		}
		// 4. 删除的节点有两个子节点
		else {
			//获取后继节点
			let successor = this.getSuccessor(current)
			if (current == this.root){
				this.root = successor
				successor.left = current.left
			}
			else if (isLeftChild){
				parent.left = successor
				successor.left = current.left
			}
			else {
				parent.right = successor
				successor.left = current.left
			}
		}
	}
	/*
	* 8. 内部方法,查找要删除节点的后继
	*/ 
	BinarySearchTree.prototype.getSuccessor = function(delNode){
		let successor = delNode
		let successorParent = delNode
		let current = delNode.right
		
		while (current != null){
			successorParent = successor
			successor = current
			current = current.left
		}	
		//后继节点不为找到的首个右子节点
		if (successor != delNode.right){
			successorParent.left = successor.right
			successor.right = delNode.right
		}
		return successor
	}
}

你可能感兴趣的:(JavaScript树结构——二叉搜索树)