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
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉排序树是一种特殊的二叉树,它满足以下条件: 1. 对于每个节点,它的左子树中的所有节点的值都小于该节点的值; 2. 对于每个节点,它的右子树中的所有节点的值都大于该节点的值; 3. 左右子树也都是二叉排序树。 为了实现二叉排序树的查找,我们需要以下步骤: 1. 从根节点开始,比较要查找的值与当前节点的值的大小关系; 2. 如果要查找的值比当前节点的值小,则进入左子树继续查找; 3. 如果要查找的值比当前节点的值大,则进入右子树继续查找; 4. 如果要查找的值与当前节点的值相等,则找到目标节点,返回该节点。 下面是使用javascript语言实现二叉排序树查找的代码示例: ```javascript class TreeNode { constructor(val) { this.val = val this.left = null this.right = null } } class BinarySearchTree { constructor() { this.root = null } insert(val) { const node = new TreeNode(val) if (!this.root) { this.root = node } else { let curr = this.root while (true) { if (val < curr.val) { if (!curr.left) { curr.left = node break } else { curr = curr.left } } else if (val > curr.val) { if (!curr.right) { curr.right = node break } else { curr = curr.right } } else { break // 值已存在,不插入 } } } } search(val) { let curr = this.root while (curr) { if (val === curr.val) { return curr } else if (val < curr.val) { curr = curr.left } else { curr = curr.right } } return null } } // 示例 const bst = new BinarySearchTree() bst.insert(5) bst.insert(3) bst.insert(7) bst.insert(2) bst.insert(4) bst.insert(6) bst.insert(8) console.log(bst.search(6)) // TreeNode { val: 6, left: null, right: null } console.log(bst.search(9)) // null ``` 上面的代码中,使用了 `TreeNode` 类表示树节点,使用 `BinarySearchTree` 类表示二叉排序树。在插入节点时,如果插入的值已存在,则不插入。在查找节点时,如果找到则返回目标节点,否则返回 `null`。可以通过示例测试查找的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值