本篇,我们用go简单的实现平衡二叉查找树。具体原理参考大佬博客即可:AVL树(一)之 图文解析 和 C语言的实现

1.节点定义

type AVLNode struct{
data int
height int
left, right *AVLNode
}

2.树的遍历

// 前序遍历
func PreTraverse(p *AVLNode) {
if p == nil {
return
}
fmt.Printf("%d:%d ", p.data, p.height)
if p.left != nil {
PreTraverse(p.left)
}
if p.right != nil {
PreTraverse(p.right)
}
} // 中序遍历
func InTraverse(p *AVLNode) {
if p == nil {
return
}
if p.left != nil {
InTraverse(p.left)
}
fmt.Printf("%d ", p.data)
if p.right != nil {
InTraverse(p.right)
}
} // 后序遍历
func PostTraverse(p *AVLNode) {
if p == nil {
return
}
if p.left != nil {
PostTraverse(p.left)
}
if p.right != nil {
PostTraverse(p.right)
}
fmt.Printf("%d ", p.data)
}

3.树的旋转

// LL的旋转
func ll_rotate(k2 *AVLNode) *AVLNode {
var k1 *AVLNode = k2.left
k2.left = k1.right
k1.right = k2 k2.height = max(height(k2.left), height(k2.right)) + 1
k1.height = max(height(k1.left), k2.height) + 1 return k1
} // RR的旋转
func rr_rotate(k1 *AVLNode) *AVLNode {
var k2 *AVLNode = k1.right
k1.right = k2.left
k2.left = k1 k1.height = max(height(k1.left), height(k1.right)) + 1
k2.height = max(height(k2.right), k1.height) + 1 return k2
} // LR的旋转
func lr_rotate(k3 *AVLNode) *AVLNode {
k3.left = rr_rotate(k3.left)
return ll_rotate(k3)
} // RL的旋转
func rl_rotate(k1 *AVLNode) *AVLNode {
k1.right = ll_rotate(k1.right)
return rr_rotate(k1)
}

4.插入节点

// 插入节点
func Add(p *AVLNode, data int) *AVLNode {
if p == nil {
p = new(AVLNode)
p.data = data
p.height = 1
return p
} if data < p.data {
p.left = Add(p.left, data)
if height(p.left) - height(p.right) == 2 {
if data > p.left.data {
fmt.Println("lr")
p = lr_rotate(p)
} else {
fmt.Println("ll")
p = ll_rotate(p)
}
}
} else if data > p.data {
p.right = Add(p.right, data)
if height(p.right) - height(p.left) == 2{
if data > p.right.data {
fmt.Println("rr")
p = rr_rotate(p)
} else {
fmt.Println("rl")
p = rl_rotate(p)
}
}
} else {
fmt.Println("Add fail: not allowed same data!")
} p.height = max(height(p.left), height(p.right)) + 1
fmt.Printf("节点:%d, 高度:%d\n", p.data, p.height) return p
}

5.查询节点

// 查询节点
func Find(p *AVLNode, data int) *AVLNode {
if p.data == data {
return p
} else if data < p.data {
if p.left != nil {
return Find(p.left, data)
}
return nil
} else {
if p.right != nil {
return Find(p.right, data)
}
return nil
}
} // 最大节点
func maxNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.right != nil {
p = p.right
}
return p
} // 最小节点
func minNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.left != nil {
p = p.left
}
return p
}

6.删除节点

// 删除节点
func Delete(p *AVLNode, data int) *AVLNode {
node := Find(p, data)
if node != nil {
return delete(p, node)
}
return nil
} func delete(p, node *AVLNode) *AVLNode {
if node.data < p.data {
p.left = delete(p.left, node)
if height(p.right) - height(p.left) == 2 {
if height(p.right.right) > height(p.right.left) {
p = rr_rotate(p)
} else {
p = rl_rotate(p)
}
}
} else if node.data > p.data {
p.right = delete(p.right, node)
if height(p.left) - height(p.right) == 2 {
if height(p.left.right) > height(p.left.left) {
p = lr_rotate(p)
} else {
p = ll_rotate(p)
}
}
} else {
// 左右孩子都非空
if (p.left != nil) && (p.right != nil) {
if height(p.left) > height(p.right) {
var max *AVLNode = maxNode(p.left)
p.data = max.data
p.left = delete(p.left, max)
} else {
var min *AVLNode = minNode(p.right)
p.data = min.data
p.right = delete(p.right, min)
}
} else {
if p.left != nil {
p = p.left
} else {
p = p.right
}
}
} if p != nil {
p.height = max(height(p.left), height(p.right)) + 1
} return p }

7.完整代码

package main

import (
"fmt"
) type AVLNode struct{
data int
height int
left, right *AVLNode
} func max(a, b int) int {
if a > b {
return a
}
return b
} func height(p *AVLNode) int {
if p != nil {
return p.height
}
return 0
} // 前序遍历
func PreTraverse(p *AVLNode) {
if p == nil {
return
} fmt.Printf("%d:%d ", p.data, p.height)
if p.left != nil {
PreTraverse(p.left)
}
if p.right != nil {
PreTraverse(p.right)
}
} // 中序遍历
func InTraverse(p *AVLNode) {
if p == nil {
return
} if p.left != nil {
InTraverse(p.left)
}
fmt.Printf("%d ", p.data)
if p.right != nil {
InTraverse(p.right)
}
} // 后序遍历
func PostTraverse(p *AVLNode) {
if p == nil {
return
} if p.left != nil {
PostTraverse(p.left)
}
if p.right != nil {
PostTraverse(p.right)
}
fmt.Printf("%d ", p.data)
} // LL的旋转
func ll_rotate(k2 *AVLNode) *AVLNode {
var k1 *AVLNode = k2.left
k2.left = k1.right
k1.right = k2 k2.height = max(height(k2.left), height(k2.right)) + 1
k1.height = max(height(k1.left), k2.height) + 1 return k1
} // RR的旋转
func rr_rotate(k1 *AVLNode) *AVLNode {
var k2 *AVLNode = k1.right
k1.right = k2.left
k2.left = k1 k1.height = max(height(k1.left), height(k1.right)) + 1
k2.height = max(height(k2.right), k1.height) + 1 return k2
} // LR的旋转
func lr_rotate(k3 *AVLNode) *AVLNode {
k3.left = rr_rotate(k3.left)
return ll_rotate(k3)
} // RL的旋转
func rl_rotate(k1 *AVLNode) *AVLNode {
k1.right = ll_rotate(k1.right)
return rr_rotate(k1)
} // 插入节点
func Add(p *AVLNode, data int) *AVLNode {
if p == nil {
p = new(AVLNode)
p.data = data
p.height = 1
return p
} if data < p.data {
p.left = Add(p.left, data)
if height(p.left) - height(p.right) == 2 {
if data > p.left.data {
fmt.Println("lr")
p = lr_rotate(p)
} else {
fmt.Println("ll")
p = ll_rotate(p)
}
}
} else if data > p.data {
p.right = Add(p.right, data)
if height(p.right) - height(p.left) == 2{
if data > p.right.data {
fmt.Println("rr")
p = rr_rotate(p)
} else {
fmt.Println("rl")
p = rl_rotate(p)
}
}
} else {
fmt.Println("Add fail: not allowed same data!")
} p.height = max(height(p.left), height(p.right)) + 1
fmt.Printf("节点:%d, 高度:%d\n", p.data, p.height) return p
} // 查询节点
func Find(p *AVLNode, data int) *AVLNode {
if p.data == data {
return p
} else if data < p.data {
if p.left != nil {
return Find(p.left, data)
}
return nil
} else {
if p.right != nil {
return Find(p.right, data)
}
return nil
}
} // 最大节点
func maxNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.right != nil {
p = p.right
}
return p
} // 最小节点
func minNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.left != nil {
p = p.left
}
return p
} // 删除节点
func Delete(p *AVLNode, data int) *AVLNode {
node := Find(p, data)
if node != nil {
return delete(p, node)
}
return nil
} func delete(p, node *AVLNode) *AVLNode {
if node.data < p.data {
p.left = delete(p.left, node)
if height(p.right) - height(p.left) == 2 {
if height(p.right.right) > height(p.right.left) {
p = rr_rotate(p)
} else {
p = rl_rotate(p)
}
}
} else if node.data > p.data {
p.right = delete(p.right, node)
if height(p.left) - height(p.right) == 2 {
if height(p.left.right) > height(p.left.left) {
p = lr_rotate(p)
} else {
p = ll_rotate(p)
}
}
} else {
// 左右孩子都非空
if (p.left != nil) && (p.right != nil) {
if height(p.left) > height(p.right) {
var max *AVLNode = maxNode(p.left)
p.data = max.data
p.left = delete(p.left, max)
} else {
var min *AVLNode = minNode(p.right)
p.data = min.data
p.right = delete(p.right, min)
}
} else {
if p.left != nil {
p = p.left
} else {
p = p.right
}
}
} if p != nil {
p.height = max(height(p.left), height(p.right)) + 1
} return p } func main() {
//num := []int{50, 30, 20, 25, 70, 90, 100}
num := []int{3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9} var root *AVLNode
for _, v := range num {
fmt.Printf("插入节点:%d\n", v)
root = Add(root, v)
} fmt.Println("前序遍历:")
PreTraverse(root)
fmt.Printf("\n") fmt.Println("中序遍历:")
InTraverse(root)
fmt.Printf("\n") fmt.Println("后序遍历:")
PostTraverse(root)
fmt.Printf("\n") avlnode := Find(root, 60)
if avlnode != nil {
fmt.Println("查询结果:")
fmt.Printf("节点:%d 左子节点:%d 右子节点:%d\n", avlnode.data, avlnode.left.data, avlnode.right.data)
} root = Delete(root, 8)
fmt.Println("删除后前序遍历:")
PreTraverse(root)
fmt.Printf("\n") fmt.Println("删除后中序遍历:")
InTraverse(root)
fmt.Printf("\n") }

最新文章

  1. mongodb分片配置
  2. [异常解决] 初玩SAE遇到的小问题——注册&amp;创建项目+MyEclipse装插件直接部署+一个简单的JSP部署实现
  3. 0022 Java学习笔记-面向对象-继承、多态、组合
  4. Objective-C学习笔记-第一天(1)
  5. GIT 在本地保存账户和密码
  6. IMetadataAware接口的特性定制Model元数据
  7. Highcharts的基本属性和方法详解
  8. CentOS 卸载已安装软件
  9. spring-cloud-turbine
  10. vs2010常见错误
  11. Centos添加硬盘分区、挂载磁盘
  12. winform timespan 两个时间的间隔(差) 分类: WinForm 2014-04-15 10:14 419人阅读 评论(0) 收藏
  13. jsp之间url传值出现中文乱码
  14. 《JavaScript 闯关记》之垃圾回收和内存管理
  15. 演练2-2:Guestbook示例应用程序
  16. 聊天工具mychat
  17. jenkins配置邮箱服务器(126邮箱)
  18. Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices
  19. B/S的学习
  20. 转载-Python单元测试框架——unittest

热门文章

  1. 线程基础知识16-线程相关类CyclicBarrier、Semaphore、Exchanger
  2. P30_全局配置 - window - 下拉刷新
  3. P25_wxss - rpx单位
  4. jquery(一:认识jquery、选择器)
  5. 如何把已安装的nodejs高版本降级为低版本(图文教程)
  6. python将一行多字符转换为多行单字符方法
  7. 图 -拓扑 topo
  8. WPF项目需要不断更新前台图片时,碰到“System.IO.IOException: 文件“xxx”正由另一进程使用“问题的解决
  9. lg8365题解
  10. JetBrains之全家桶破解