GOLANG实现的一个avl tree api

用golang实现了一个avl tree的api。

avlTree.go

/*
** an avl tree api:
//==>> operator tree api:
//insert an x to AvlTree, invoker format: t = tree.Insert(t, x)
func Insert(tree *AvlNode, x ElementType) *AvlNode 
//del an x in AvlTree, invoker format: t = tree.Delete(t, x)
func Delete(tree *AvlNode, x ElementType) *AvlNode 	
//make a tree to be empty
func MakeEmpty( tree *AvlNode) *AvlNode 
//==>> print tree api:
//draw a tree
func DrawTree1(tree *AvlNode) 
//leve print a tree
func LevePrintTree(tree *AvlNode) 
//middle print a tree
func MidPrintTree(tree *AvlNode) 
//prev print a tree
func PrevPrintTree(tree *AvlNode) {
//return the height of the node
func (node *AvlNode) NodeHeight() int 
//==>> find   node  api:
//find Element x position in the avl tree
func (tree *AvlNode) Find(x ElementType) *AvlNode
//find min elem in the tree
func (tree *AvlNode) FinMin() *AvlNode 
//find max elem in the tree
func (tree *AvlNode) FinMax() *AvlNode 
*/

package tree

import (
	"fmt"
	"math"
)


type AvlNode struct {
	Elem ElementType
	Left *AvlNode
	Right *AvlNode
	Height int
}

type ElementType int

func If(condition bool, truVal, falseVal interface{}) interface{} {
	if condition {
		return truVal
	}
	return falseVal
}

//make a tree to be empty
func MakeEmpty( tree *AvlNode) *AvlNode {	
	//free left child
	if tree.Left != nil {		
		tree.Left = MakeEmpty(tree.Left)		
	}  
	//free right child
	if tree.Right != nil {
		tree.Right = MakeEmpty(tree.Right)
	} 
	//a leaf, just return nil, a gc will free the memory
	return nil	
}

func printSpace(spaceNum int) {	
	for i := 0; i < spaceNum; i++ {
		fmt.Printf("  ")
	}
}

//draw a tree
func DrawTree1(tree *AvlNode) {		
	var s [] *AvlNode
	var nextLine  *AvlNode	
	var curH int
	newLine := true		
	
	for tree != nil {		
		curH = tree.NodeHeight()		
		if nextLine == tree {			
			fmt.Println()				
			//maxLineNum = int(math.Pow(2, float64(curL)))
			newLine = true
			nextLine = nil			
		} 
		
		printSpace( int(math.Pow(2, float64(curH-1)) ) )
		
		if !newLine {
			if curH == 0 || curH == 1  {
				printSpace(1)
			} else {
				printSpace( int(math.Pow(2, float64(curH-1))) )
			}			
		} else {
			newLine = false	
			if curH == 0 {
				printSpace(1)
			}
		}			
		
		fmt.Printf("%v ", tree.Elem)
		
		if tree.Left != nil {
			if nextLine == nil {
				nextLine = tree.Left
			}
			s = append(s, tree.Left)
		}
		if tree.Right != nil {
			if nextLine == nil {
				nextLine = tree.Right
			}
			s = append(s, tree.Right)
		}
		
		if len(s) > 0 {
			tree = s[0]
			s = s[1:]
		} else {
			tree = nil
		}		
	}	
	
	fmt.Println()
}

//leve print a tree
func LevePrintTree(tree *AvlNode) {
	var s [] *AvlNode
	for tree != nil {	
		fmt.Printf("%v ", tree.Elem)
		
		if tree.Left != nil {
			s = append(s, tree.Left)
		}
		if tree.Right != nil {
			s = append(s, tree.Right)
		}
		
		if len(s) > 0 {
			tree = s[0]
			s = s[1:]
		} else {
			tree = nil
		}		
	}	
	
	fmt.Println()
	
}

//middle print a tree
func MidPrintTree(tree *AvlNode) {
	if (tree != nil ) {
		MidPrintTree(tree.Left)
		fmt.Printf(" %v ", tree.Elem)
		MidPrintTree(tree.Right)
	}	
}
//prev print a tree
func PrevPrintTree(tree *AvlNode) {
	if (tree != nil ) {
		fmt.Printf(" %v ", tree.Elem)
		PrevPrintTree(tree.Left)		
		PrevPrintTree(tree.Right)
	}	
}

//find Element x position in the avl tree
func (tree *AvlNode) Find(x ElementType) *AvlNode {
	if tree != nil {
		if x < tree.Elem {
			//find left
			return tree.Left.Find(x)
		} else if x > tree.Elem {
			//find right
			return tree.Right.Find(x)
		} else if x == tree.Elem {
			//we find that
			return tree
		}
	} 

	//can not found or empty tree
	return nil		
}

//find min elem in the tree
func (tree *AvlNode) FinMin() *AvlNode {
	if tree != nil {
		if tree.Left != nil {
			return tree.Left.FinMin()
		} else {
			return tree
		}
		
	} else {
		return nil
	}
}

//find max elem in the tree
func (tree *AvlNode) FinMax() *AvlNode {
	if tree != nil {
		if tree.Right != nil {
			return tree.Right.FinMax()
		} else {
			return tree
		}
		
	} else {
		return nil
	}
}

//return the height of the node
func (node *AvlNode) NodeHeight() int {
	if node == nil {
		return -1
	} else {
		return node.Height
	}
}

//insert an x to AvlTree, invoker format: t = tree.Insert(t, x)
func Insert(tree *AvlNode, x ElementType) *AvlNode {	
	if tree == nil {
		//tree = new(AvlNode)
		tree = &AvlNode { 
			Elem : x,			
			Height : 0,
		}
	} else if x < tree.Elem {
		tree.Left = Insert(tree.Left, x)
		if tree.Left.NodeHeight() - tree.Right.NodeHeight() == 2 {
			if x < tree.Left.Elem { //left left
				tree = singleLeftRotate(tree)
			} else { //left right
				tree = doubleRotateLeftRight(tree)
			}
		}
	} else if x > tree.Elem {
		tree.Right = Insert(tree.Right, x)
		if tree.Right.NodeHeight() - tree.Left.NodeHeight() == 2 {
			if x > tree.Right.Elem {
				tree = singleRightRotate(tree)
			} else {
				tree = doubleRotateRightLeft(tree)
			}
		}
	} else {
		//x existed, we do nothing.
	}

	tree.Height = If(tree.Left.NodeHeight() > tree.Right.NodeHeight(), 
					tree.Left.NodeHeight(), tree.Right.NodeHeight()).(int) + 1

	return tree
}

//del an x in AvlTree, invoker format: t = tree.Delete(t, x)
func Delete(tree *AvlNode, x ElementType) *AvlNode {	
	var tmp *AvlNode
	if tree != nil {
		if x < tree.Elem {
			tree.Left = Delete(tree.Left, x)	
			if tree.Right.NodeHeight() - tree.Left.NodeHeight() == 2 {
				if tree.Right.Right != nil {
					tree = singleRightRotate(tree)
				} else {
					tree = doubleRotateRightLeft(tree)
				}			
			} else {
				tree.Height = If(tree.Left.NodeHeight() > tree.Right.NodeHeight(), 
						tree.Left.NodeHeight(), tree.Right.NodeHeight()).(int) +1
			}
		} else if x > tree.Elem {
			tree.Right = Delete(tree.Right, x)
			if tree.Left.NodeHeight() - tree.Right.NodeHeight() == 2 {
				if tree.Left.Left != nil {
					tree = singleLeftRotate(tree)
				} else {
					tree = doubleRotateLeftRight(tree)
				}
							
			} else {
				tree.Height = If(tree.Left.NodeHeight() > tree.Right.NodeHeight(), 
						tree.Left.NodeHeight(), tree.Right.NodeHeight()).(int) +1
			}			
		} else if tree.Left != nil && tree.Right != nil {
			tmp = tree.Right.FinMin()
			tree.Elem = tmp.Elem
			tree.Right = Delete(tree.Right, tmp.Elem)
			
		} else {			
			if tree.Left == nil {
				tree = tree.Right
			} else if tree.Right == nil {
				tree = tree.Left
			}			
		}		
	}

	
	return tree
}

/*
//return the max height
func maxHeight(node1, node2 *AvlNode ) int {
	if node1.Height > node2.Height {
		return node1.Height
	} else {
		return node2.Height
	}	
}
*/


//left rotate a tree, and update node's height, return the new tree 
func singleLeftRotate(tree *AvlNode) *AvlNode {
	var k1 *AvlNode
	if tree != nil {
		k1 = tree.Left
		tree.Left = k1.Right
		k1.Right = tree
		
		//update height
		tree.Height = If(tree.Left.NodeHeight() > tree.Right.NodeHeight(), 
						tree.Left.NodeHeight(), tree.Right.NodeHeight()).(int) +1
		k1.Height = If(k1.Left.NodeHeight() > k1.Right.NodeHeight(), 
						k1.Left.NodeHeight(), k1.Right.NodeHeight()).(int) +1	

		tree = k1
	}

	return tree
}

//right rotate a tree, and update node's height, return the new tree
func singleRightRotate(tree *AvlNode) *AvlNode {
	var k1 *AvlNode
	if tree != nil {
		k1 = tree.Right
		tree.Right = k1.Left
		k1.Left = tree
		
		//update height
		tree.Height = If(tree.Left.NodeHeight() > tree.Right.NodeHeight(), 
						tree.Left.NodeHeight(), tree.Right.NodeHeight()).(int) +1
		k1.Height = If(k1.Left.NodeHeight() > k1.Right.NodeHeight(), 
						k1.Left.NodeHeight(), k1.Right.NodeHeight()).(int) +1	

		tree = k1
	}

	return tree
}

//k3 a tree base, k2: k3's left childe, k1: k2's right childe
//right rotate k2 & k1, left rotate k3 & k3's left child
//return a new tree
func doubleRotateLeftRight(k3 *AvlNode) *AvlNode  {
	//right rotatel between k2 & k1
	k3.Left = singleRightRotate(k3.Left)

	//left rotate between k3 and his left child
	return singleLeftRotate(k3)
}

//k3 a tree base, k2: k3's left childe, k1: k2's right childe
//left rotate k2 & k1, right rotate k3 & k3's left child
//return a new tree
func doubleRotateRightLeft(k3 *AvlNode) *AvlNode  {
	//left rotatel between k2 & k1
	k3.Right = singleLeftRotate(k3.Right)

	//right rotate between k3 and his left child
	return singleRightRotate(k3)
}

 

使用golang的test框架测试:

avlTree_test.go

package tree

import (
	"testing"
	"math/rand"
	"fmt"
	"time"	
)

func TestCreateTree(t *testing.T) {
	r := rand.New(rand.NewSource(10))	
	r.Seed(time.Now().UnixNano())
	a := r.Perm(30)	
	fmt.Println("create a slice:", a)
	var tree *AvlNode
	for _, v := range a {
		tree = Insert(tree, ElementType(v)) 
	}
		
	fmt.Println("tree created\nmidl read:")
	MidPrintTree(tree)
	fmt.Println("\nleve read:")
	LevePrintTree(tree)
	fmt.Println("\ndraw:")
	DrawTree1(tree);
	fmt.Printf("\nmin: %v, max:%v\n", tree.FinMin().Elem, tree.FinMax().Elem)		
}

测试结果:

root@ubuntu01:tree# go test
draw the avl tree:
                                16 
                5                                 21 
    1                 9         18                 25 
  0     3     7         12   17     19     23         27 
  2   4   6   8     10     14   20   22   24   26     29 
  11   13   15   28 

min: 0, max:29
PASS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值