数据结构与算法 — 二叉查找树的代码实现(Golang)_go语言实现二叉树的插入查找和删除

80 阅读2分钟

1 定义

  1. 如果左子树不为空,且左子树上所有节点的值均小于根节点的值。
  2. 如果右子树不为空,则右子树上所有节点的值均大于根节点的值。
  3. 左、右子树也都是二叉查找树。

总结:就是从左、根、右具有单调递增的二叉树就是二叉查找树。
时间复杂度:O(logn)和树的层级成正比。

2 有序性

二叉查找树不仅可以用于查找,还可以维持节点的有序性。
对二叉查找树使用中序遍历的操作,访问左子树、根节点、右子树,出来的结果就是一个具有单调递增性质的数据。所以二叉查找树又被称为二叉排序树。

3 查找、插入

二叉查找树的查找和插入的过程基本一致,都是从根节点依次和查找【插入】的数据比较大小,然后判断查找【插入】的位置。

4 代码实现

/\*\*
查找
\*/
func BinaryTreeSearch(rootNode \*Node, data int) (targetNode \*Node) {
	if rootNode == nil { //如果根节点为nil,则为搜索失败,即targetNode=nil
		targetNode = nil
	} else {
		if rootNode.Data == data {
			targetNode = rootNode
		} else if rootNode.Data > data {
			targetNode = BinaryTreeSearch(rootNode.Left, data) //递归搜索左子树
		} else if rootNode.Data < data {
			targetNode = BinaryTreeSearch(rootNode.Right, data) //递归搜索右子树
		}
	}
	return targetNode
}

/\*\*
插入
\*/
func InsertElement(rootNode \*Node, data int) (bool, error) {
	insertResult := false
	err := errors.New("插入失败")

	insertNode := &Node{
		Data:  data,
		Left:  nil,
		Right: nil,
	}

	if rootNode == nil { //根节点为nil时直接插入到根节点处
		rootNode = insertNode
		insertResult = true
	} else {
		if rootNode.Data == data {
			insertResult = false
			err = errors.New("二叉查找树中已存在该元素")
		} else if rootNode.Data > data { //根节点的值大于待插入的值
			if rootNode.Left != nil { //判断是否有左孩子,若有则继续递归左孩子,若无则直接插入到左孩子位置
				insertResult, err = InsertElement(rootNode.Left, data)
			} else {
				rootNode.Left = insertNode
				insertResult = true
			}
		} else if rootNode.Data < data { //根节点的值小于待插入的值
			if rootNode.Right != nil { //判断是否有右孩子,若有则继续递归右孩子,若无则直接插入到右孩子位置
				insertResult, err = InsertElement(rootNode.Right, data)
			} else {
				rootNode.Right = insertNode
				insertResult = true
			}
		}
	}
	return insertResult, err
}

5 删除

二叉查找树的删除有三种情况:
1、待删除的节点是叶子节点,删除后不需要调整树的结构,可以直接删除。
2、待删除的节点是根节点,有一个孩子节点【左孩子结点】,节点删除后,直接将其左孩子节点放到待删除节点的位置即可。
3、待删除节点有两个子节点,一般从其右子树开始递归到最底层的左叶子节点放到待删除节点的位置。【叙述上仍需完善】

5.1 代码实现

/\*\*
删除
\*/
func DeleteElement(rootNode \*Node, data int) bool {
	//先找到当前节点的父节点
	deleteResult := false

	parentNode := &Node{ //待删除的元素构成的节点
		Data:  data,
		Left:  nil,
		Right: nil,
	}
	targetNode := rootNode

	for targetNode.Data != data { //当前节点的值不等于待删除的值时,将当前节点作为父节点
		parentNode = targetNode
		if data > targetNode.Data {
			targetNode = targetNode.Right
		} else {
			targetNode = targetNode.Left
		}
		if targetNode == nil {
			deleteResult = false
		}
	}

	// 待删除结点没有子节点
	if targetNode.Right == nil && targetNode.Left == nil {
		if targetNode == rootNode {
			//待删除结点是根结点
			rootNode = nil
		} else {
			if parentNode.Right == targetNode {
				parentNode.Right = nil
			} else {
				parentNode.Left = nil
			}
		}
	} else if targetNode.Left == nil { //待删除结点有一个子结点(右)
		if targetNode == rootNode {
			rootNode = targetNode.Right
		} else if parentNode.Right == targetNode {


![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/c5a585f830ce4bcf95b115a8a9bbda46~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1770658137&x-signature=AyjblNuQkA0kXOZnVolZsugaWLg%3D)
![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/b8e3e61a31274593ab0ae2695ac50ec0~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1770658137&x-signature=cTMC4e4tKtA1r4wDeQpRD4mqq0E%3D)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://gitee.com/vip204888)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**