golang实现AVL树算法 【AVL树】【算法】【golang】

本文介绍了一种使用Golang实现的AVL树算法,包括基本的插入、删除、旋转等操作,并通过具体示例展示了如何利用AVL树解决存在重复元素III的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

golang avl树算法

package main

import (
	"fmt"
	"strings"
)



func abs(val int) int {
	if val < 0 { return -val }
	return val
}




var nodeCnt int

type Node struct {
	val         int
	left, right *Node
	h           int
}

func max(i, j int) int {
	if i > j {
		return i
	}
	return j
}
func min(i, j int) int {
	if i < j {
		return i
	}
	return j
}
func (node *Node) height() int {
	if node == nil {
		return 0
	}
	return node.h
}

// 对节点y进行向右旋转操作,返回旋转后新的根节点x
//        y                              x
//       / \                           /   \
//      x   T4     向右旋转 (y)        z     y
//     / \       - - - - - - - ->    / \   / \
//    z   T3                       T1  T2 T3 T4
//   / \
// T1   T2
func adjustLeft(y *Node) *Node {
	if y == nil {
		panic("invalid node")
	}
	var x = y.left
	y.left = x.right
	x.right = y
	y.h = max(y.left.height(), y.right.height()) + 1
	x.h = max(x.left.height(), x.right.height()) + 1
	return x

}

/*
	  y                =>          x
   a      x                      y
        b    c                     xxxxxx
           e   d
*/

// right 重,左旋转
func adjustRight(y *Node) *Node {
	if y == nil {
		panic("invalid node")
	}
	var x = y.right
	// x  >= y
	y.right = x.left
	x.left = y
	y.h = max(y.left.height(), y.right.height()) + 1
	x.h = max(x.left.height(), x.right.height()) + 1
	return x

}

// left 重, left.right 重
func adjustLeftRight(node *Node) *Node {
	//左子树的右节点
	node.left = adjustRight(node.left)
	// left left rotation
	return adjustLeft(node)
}

// right 重,并且 right.left 重
func adjustRightLeft(node *Node) *Node {
	node.right = adjustLeft(node.right)

	return adjustRight(node)
}

func insertNode(node *Node, val int) *Node {
	if node == nil {
		nodeCnt++
		return &Node{val: val, h: 1}
	}
	switch {
	case node.val < val:
		// current < val , to right find
		node.right = insertNode(node.right, val)
		// 插入 右边节点,只能是  height(right) >= height(left)
		if node.right.height()-node.left.height() == 2 {
			// adjust right
			if val > node.right.val {
				// right 重,right.right也重
				node = adjustRight(node)
			} else {
				// right 重,right.left重
				node = adjustRightLeft(node)
			}
		}
	case node.val > val:
		// 去插入到左边节点
		node.left = insertNode(node.left, val)
		if node.left.height()-node.right.height() == 2 {
			// 判断 left.val < val
			if node.left.val > val {
				// left重,left.left也重, 处理 ll
				node = adjustLeft(node)
			} else {
				//left, left.right重
				node = adjustLeftRight(node)
			}
		}
	default:
		//log.Println("exists")

	}
	node.h = max(node.left.height(), node.right.height()) + 1
	return node
}
func findMinNode(node *Node) *Node {
	if node == nil {
		return nil
	}
	for node.left != nil {
		node = node.left
	}
	return node
}
func findMaxNode(node *Node) *Node {
	if node == nil {
		return nil
	}
	for node.right != nil {
		node = node.right

	}
	return node
}

// >= val => 天花板,下边界
func findFloorNode(node *Node, val int) *Node {
Loop:
	for node != nil {
		if node.val == val {
			//return node
			break Loop
		} else if node.val < val {
			// to right
			node = node.right
		} else {
			//to left, if left is nil , return current Node
			//node = node.right
			left := findFloorNode(node.left, val)
			if left != nil && left.val < node.val {
				node = left
			}
			break Loop
			// left is small

		}
	}
	return node
}

// <= val 的最大节点
func findCeilNode(node *Node, val int) *Node {
	// 早到 比 val 小的
	if node == nil {
		return nil
	}
find:
	for node != nil {
		if node.val == val {
			break find
		} else if node.val > val {
			// 比他大 , 左边 的 可能也比他大
			node = node.left
		} else {
			// node.val < val , to right find  <= val first
			var s = findCeilNode(node.right, val)
			if s != nil && s.val > node.val {
				node = s
			}
			break find

		}
	}
	return node
}
func adjustNode(node *Node) *Node {
	// adjust node
	switch node.left.height() - node.right.height() {
	case 2:
		// left 重
		//var left = node.left
		if node.left.height() > node.right.height() {
			node = adjustLeft(node)
		} else {
			node = adjustLeftRight(node)
		}

	case -2:
		if node.right.right.height() > node.right.left.height() {
			// right right 重
			node = adjustRight(node)
		} else {
			node = adjustRightLeft(node)
		}

	}
	return node
}

func deleteNode(node *Node, val int) *Node {
	if node == nil {
		return nil
	}
	if node.val < val {
		node.right = deleteNode(node.right, val)
	} else if node.val > val {
		// to left delete
		node.left = deleteNode(node.left, val)
	} else {
		// delete current
		nodeCnt--
		if node.left == nil {
			if node.right == nil {
				//delete one
				node = nil
			} else {
				// return node.right
				node = node.right
			}
		} else {
			if node.right == nil {
				//node.left != nil
				node = node.left
			} else {
				// node.left != nil  node.right !=nil
				//前驱节点
				var nextNode = findMinNode(node.right)
				node.val = nextNode.val
				//委托 删除 minNode ,  这边不好删除,直接 取巧 ,覆盖值即可
				node.right = deleteNode(node.right, nextNode.val)
			}
		}
	}
	if node != nil {
		//跳转高度
		node.h = max(node.left.height(), node.right.height()) + 1
		node = adjustNode(node)
	}
	return node
}

//func rightRotationNode(node *Node) *Node {
//	var right = node.right
//	node.right = node.left
//	node
//}
func ascPrint(node *Node) {
	if node == nil {
		return
	}
	ascPrint(node.left)
	fmt.Printf("%v,", node.val)
	ascPrint(node.right)
}

func (o *Node)String() string {
	return fmt.Sprintf("%v ",o.val)
}
func (o *Node) draw(prefix string, isTail bool, str *strings.Builder) {
	if o.right != nil {
		newPrefix := prefix
		if isTail {
			newPrefix += "│   "
		} else {
			newPrefix += "    "
		}
		o.right.draw(newPrefix, false, str)
	}
	str.WriteString(prefix)
	if isTail {
		str.WriteString("└── ")
	} else {
		str.WriteString( "┌── ")
	}
	str.WriteString(o.String() + "\n")
	if o.left != nil {
		newPrefix := prefix
		if isTail {
			newPrefix += "    "
		} else {
			newPrefix += "│   "
		}
		o.left.draw(newPrefix, true, str)
	}
}

func main() {
	var root *Node
	root = insertNode(root,1)
	root = insertNode(root,1)
	root = insertNode(root,1)
	root = insertNode(root,1)
	for i:=88;i>=1;i-- {
		root = insertNode(root,i)
	}
	var s strings.Builder
	root.draw("  @        ", false, &s)
	fmt.Println(s.String())
}

例题

220. 存在重复元素 III

Difficulty: **给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。 如果存在则返回 true,不存在返回 false。 示例 1: 输入:nums = [1,2,3,1], k = 3, t = 0 输出:true 示例 2: 输入:nums = [1,0,1,1], k = 1, t = 2 输出:true 示例 3: 输入:nums = [1,5,9,1,5,9], k = 2, t = 3 输出:false 提示: 0 <= nums.length <= 2 * 104 -231 <= nums[i] <= 231 - 1 0 <= k <= 104 0 <= t <= 231 - 1 **

给你一个整数数组 nums 和两个整数 kt 。请你判断是否存在 两个不同下标 ij,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k

如果存在则返回 true,不存在返回 false

示例 1:

输入:nums = [1,2,3,1], k = 3, t = 0
输出:true

示例 2:

输入:nums = [1,0,1,1], k = 1, t = 2
输出:true

示例 3:

输入:nums = [1,5,9,1,5,9], k = 2, t = 3
输出:false

提示:

  • 0 <= nums.length <= 2 * 10<sup>4</sup>
  • -2<sup>31</sup> <= nums[i] <= 2<sup>31</sup> - 1
  • 0 <= k <= 10<sup>4</sup>
  • 0 <= t <= 2<sup>31</sup> - 1
Solution

Language: ****

func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool {
   var root *Node
   
    
   //类似滑动窗口的算法
   for i,n := 0,len(nums);i<n;i++ {
      
       // 找到  
       //  abs(nums[i] - nums[x]) <= t  =>  找上界 找小的 =》  nums[i] -t  <=  x <= nums[i] + t
       
       var node = findFloorNode(root,nums[i] - t)
       if node != nil &&  node.val <= nums[i] + t {
           //满足   nums[i] -t <=  node.val <=  nums[i] + t => 即满足  表达式
           return true 
       }
       
       root = insertNode(root,nums[i])

       // then can not find 
       if i>=k {
           //删除划出窗口的元素
           root = deleteNode(root,nums[i-k])
       }

   }
   return false 
}

func abs(val int) int {
   if val < 0 { return -val }
   return val 
}




var nodeCnt int

type Node struct {
   val         int
   left, right *Node
   h           int
}

func max(i, j int) int {
   if i > j {
   	return i
   }
   return j
}
func min(i, j int) int {
   if i < j {
   	return i
   }
   return j
}
func (node *Node) height() int {
   if node == nil {
   	return 0
   }
   return node.h
}

// 对节点y进行向右旋转操作,返回旋转后新的根节点x
//        y                              x
//       / \                           /   \
//      x   T4     向右旋转 (y)        z     y
//     / \       - - - - - - - ->    / \   / \
//    z   T3                       T1  T2 T3 T4
//   / \
// T1   T2
func adjustLeft(y *Node) *Node {
   if y == nil {
   	panic("invalid node")
   }
   var x = y.left
   y.left = x.right
   x.right = y
   y.h = max(y.left.height(), y.right.height()) + 1
   x.h = max(x.left.height(), x.right.height()) + 1
   return x
    
}

/*
     y                =>          x
  a      x                      y
       b    c                     xxxxxx
          e   d
*/

// right 重,左旋转
func adjustRight(y *Node) *Node {
   if y == nil {
   	panic("invalid node")
   }
   var x = y.right
   // x  >= y
   y.right = x.left
   x.left = y
   y.h = max(y.left.height(), y.right.height()) + 1
   x.h = max(x.left.height(), x.right.height()) + 1
   return x

}

// left 重, left.right 重
func adjustLeftRight(node *Node) *Node {
   //左子树的右节点
   node.left = adjustRight(node.left)
   // left left rotation
   return adjustLeft(node)
}

// right 重,并且 right.left 重
func adjustRightLeft(node *Node) *Node {
   node.right = adjustLeft(node.right)

   return adjustRight(node)
}

func insertNode(node *Node, val int) *Node {
   if node == nil {
   	nodeCnt++
   	return &Node{val: val, h: 1}
   }
   switch {
   case node.val < val:
   	// current < val , to right find
   	node.right = insertNode(node.right, val)
   	// 插入 右边节点,只能是  height(right) >= height(left)
   	if node.right.height()-node.left.height() == 2 {
   		// adjust right
   		if val > node.right.val {
   			// right 重,right.right也重
   			node = adjustRight(node)
   		} else {
   			// right 重,right.left重
   			node = adjustRightLeft(node)
   		}
   	}
   case node.val > val:
   	// 去插入到左边节点
   	node.left = insertNode(node.left, val)
   	if node.left.height()-node.right.height() == 2 {
   		// 判断 left.val < val
   		if node.left.val > val {
   			// left重,left.left也重, 处理 ll
   			node = adjustLeft(node)
   		} else {
   			//left, left.right重
   			node = adjustLeftRight(node)
   		}
   	}
   default:
   	//log.Println("exists")

   }
   node.h = max(node.left.height(), node.right.height()) + 1
   return node
}
func findMinNode(node *Node) *Node {
   if node == nil {
   	return nil
   }
   for node.left != nil {
   	node = node.left
   }
   return node
}
func findMaxNode(node *Node) *Node {
   if node == nil {
   	return nil
   }
   for node.right != nil {
   	node = node.right

   }
   return node
}

// >= val => 天花板,下边界
func findFloorNode(node *Node, val int) *Node {
Loop:
   for node != nil {
   	if node.val == val {
   		//return node
   		break Loop
   	} else if node.val < val {
   		// to right
   		node = node.right
   	} else {
   		//to left, if left is nil , return current Node
   		//node = node.right
   		left := findFloorNode(node.left, val)
   		if left != nil && left.val < node.val {
   			node = left
   		}
   		break Loop
   		// left is small

   	}
   }
   return node
}

// <= val 的最大节点
func findCeilNode(node *Node, val int) *Node {
   // 早到 比 val 小的
   if node == nil {
   	return nil
   }
find:
   for node != nil {
   	if node.val == val {
   		break find
   	} else if node.val > val {
   		// 比他大 , 左边 的 可能也比他大
   		node = node.left
   	} else {
   		// node.val < val , to right find  <= val first
   		var s = findCeilNode(node.right, val)
   		if s != nil && s.val > node.val {
   			node = s
   		}
   		break find

   	}
   }
   return node
}
func adjustNode(node *Node) *Node {
   // adjust node
   switch node.left.height() - node.right.height() {
   case 2:
   	// left 重
   	//var left = node.left
   	if node.left.height() > node.right.height() {
   		node = adjustLeft(node)
   	} else {
   		node = adjustLeftRight(node)
   	}

   case -2:
   	if node.right.right.height() > node.right.left.height() {
   		// right right 重
   		node = adjustRight(node)
   	} else {
   		node = adjustRightLeft(node)
   	}

   }
   return node
}

func deleteNode(node *Node, val int) *Node {
   if node == nil {
   	return nil
   }
   if node.val < val {
   	node.right = deleteNode(node.right, val)
   } else if node.val > val {
   	// to left delete
   	node.left = deleteNode(node.left, val)
   } else {
   	// delete current
   	nodeCnt--
   	if node.left == nil {
   		if node.right == nil {
   			//delete one
   			node = nil
   		} else {
   			// return node.right
   			node = node.right
   		}
   	} else {
   		if node.right == nil {
   			//node.left != nil
   			node = node.left
   		} else {
   			// node.left != nil  node.right !=nil
   			//前驱节点
   			var nextNode = findMinNode(node.right)
   			node.val = nextNode.val
   			//委托 删除 minNode ,  这边不好删除,直接 取巧 ,覆盖值即可
   			node.right = deleteNode(node.right, nextNode.val)
   		}
   	}
   }
   if node != nil {
   	//跳转高度
   	node.h = max(node.left.height(), node.right.height()) + 1
   	node = adjustNode(node)
   }
   return node
}

//func rightRotationNode(node *Node) *Node {
//	var right = node.right
//	node.right = node.left
//	node
//}
func ascPrint(node *Node) {
   if node == nil {
   	return
   }
   ascPrint(node.left)
   fmt.Printf("%v,", node.val)
   ascPrint(node.right)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值