数据结构-二叉树

95 阅读5分钟

  • 是一种递归数据结构
  • 有且只有一个根节点
  • 当n>1时,其余节点可分为m(m>0)个互不相交的有限集合,其每个集合本身又都是一棵树,并且称为根的子树

二叉树

二叉树是一种特殊的树形结构,二叉树中每个节点至多有两颗子树,称为左子树、右子树

  • 满二叉树:如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
img
  • 完全二叉树:若二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

img

二叉树链接存储结构

1、节点定义

每个节点设置三个域:左指针域、值域、右指针域

LeftChildDataRightChild

链接存储定义:

 type Node struct{
     Left *Node
     Data interface{}
     Right *Node
 }

2、接口定义

(1)、Initer 接口:Initer 接口提供方法 SetData() 可以对节点的 Data 字段进行初始化

 type Initer interface{
     SetData(data interface{})
 }

SetData() 方法

 func (n *Node) SetData(data interface{}){
     n.Data = data
 }

(2)、Operater 接口:提供三个方法:PrintBT()、Depth()、LeafCount(),对二叉树进行输出、深度计算、子叶统计等基本操作

 type Operater interface{
     PrintBT()
     Depth()
     LeafCount()
 }

PrintBT() 方法

 func (n *Node) PrintBT(){
     PrintBT(n)
 }

Depth() 方法

 func (n *Node) Depth() int{
     return Depth(n)
 }

LeafCount() 方法

 func (n *Node) LeafCount() int{
     return LeafCount(n)
 }

(3)、Order 接口:提供三个方法:PreOrder()、InOrder()、PostOrder(),分别可以实现前序遍历、中序遍历、后序遍历

 type Order interface{
     PreOrder()
     InOrder()
     PostOrder()
 }

PreOrder() 方法

 func (n *Node) PreOrder(){
     PreOrder(n)
 }

InOrder() 方法

 func (n *Node) InOrder(){
     InOrder(n)
 }

PostOrder() 方法

 func (n *Node) PostOrder(){
     PostOrder(n)
 }

3、底层函数设计

(1)、NewNode 函数:按照链接存储方式生成一个新的二叉树节点,参数left指向左指针域,参数right指向右指针域

 func NewNode(left, right *Node) *Node{
     return &Node{left, nil, right}
 }

(2)、PrintBT 函数:输出一个给定二叉树的嵌套括号表示

首先输出根节点,再依次输出左、右子树;依次输出的左、右子树要至少有一个不为空,否则不输出。

 func PrintBT(n *Node){
     if n != nil {
         fmt.Printf("%v", n.Data)
         if n.Left != nil || n.Right != nil {
             fmt.Printf("( ")
             PrintBT(n.Left)
             if n.Right != nil {
                 fmt.Printf(",")
             }
             PrintBT(n.Right)
             fmt.Printf(") ")
         }
     }
 }

(3)、Depth 函数:采用递归算法,计算二叉树的深度

若一颗二叉树为空,则其深度为0;否则,其深度等于左子树或右子树的最大深度加1。

 func Depth(n *Node) int {
     var depleft, depright int
     if n == nil {
         return 0
     }else {
         depleft = Depth(n.Left)
         depright = Depth(n.Right)
         if depleft > depright {
             return depleft + 1
         }else {
             return depright + 1
         }
     }
 }

(4)、LeafCount 函数:采用递归算法,统计二叉树叶子节点数

若一颗二叉树为空,则其叶子节点数为0;若一颗二叉树的左、右子树为空,则其叶子节点数为0;否则叶子数等于左子树与右子树叶子总数之和,

 func LeafCount(n *Node) int {
     if n == nil {
         return 0
     }else if (n.Left == nil) && (n.Right == nil) {
         return 1
     }else {
         return (LeafCount(n.Left) + LeafCount(n.Right))
     }
 }

(5)、PreOrder 函数:采用递归算法,对二叉树进行前序遍历

先访问根节点,再访问左子树,最后访问右子树,每个节点仅访问一次

 func PreOrder(n *Node){
     if n != nil {
         fmt.Printf("%v", n.Data)
         PreOrder(n.Left)
         PreOrder(n.Right)
     }
 }

(6)、InOrder 函数:采用递归算法,对二叉树进行中序遍历

先访问左子树,再访问根节点,最后访问右子树,每个节点仅访问一次

 func InOrder(n *Node){
     if n != nil {
         PreOrder(n.Left)
         fmt.Printf("%v", n.Data)
         PreOrder(n.Right)
     }
 }

(7)、PostOrder 函数:采用递归算法,对二叉树进行后序遍历

先访问左子树,再访问右子树,最后访问根节点,每个节点仅访问一次

 func PostOrder(n *Node) {
     if n != nil {
         PreOrder(n.Left)
         PreOrder(n.Right)
         fmt.Printf("%v", n.Data)
     }
 }

二叉树基本应用测试

package main

import (
	"fmt"
)

func main() {
	fmt.Printf("---------二叉树的创建---------\n")
	//创建根节点
	root := NewNode(nil, nil)
	root.SetData("root node")

	//创建左子树
	a := NewNode(nil, nil)
	a.SetData("left node")
	al := NewNode(nil, nil)
	al.SetData(100)
	ar := NewNode(nil, nil)
	ar.SetData(3.14)
	a.Left = al
	a.Right = ar

	//创建右子树
	b := NewNode(nil, nil)
	b.SetData("right node")
	root.Left = a
	root.Right = b
	root.PrintBT()

	fmt.Printf("\n\n---------二叉树的基本操作---------\n")
	//使用Operater接口实现对二叉树的基本操作
	//var it Operater
	//it = root
	root.PrintBT()
	fmt.Println()
	fmt.Println("此二叉树的深度为:", root.Depth())
	fmt.Println("此二叉树的叶子节点数为:", root.LeafCount())

	fmt.Printf("\n---------二叉树的遍历---------\n")
	//使用Order接口实现对二叉树的基本操作
	var it Order
	it = root
	it.PreOrder() //前序遍历
	fmt.Println()
	it.InOrder() //中序遍历
	fmt.Println()
	it.PostOrder() //后序遍历
}

type Node struct {
	Left  *Node
	Data  interface{}
	Right *Node
}

type Initer interface {
	SetData(data interface{})
}

func (n *Node) SetData(data interface{}) {
	n.Data = data
}

type Operater interface {
	PrintBT()
	Depth()
	LeafCount()
}

func (n *Node) PrintBT() {
	PrintBT(n)
}

func (n *Node) Depth() int {
	return Depth(n)
}

func (n *Node) LeafCount() int {
	return LeafCount(n)
}

type Order interface {
	PreOrder()
	InOrder()
	PostOrder()
}

func (n *Node) PreOrder() {
	PreOrder(n)
}

func (n *Node) InOrder() {
	InOrder(n)
}

func (n *Node) PostOrder() {
	PostOrder(n)
}

func NewNode(left, right *Node) *Node {
	return &Node{left, nil, right}
}

func PrintBT(n *Node) {
	if n != nil {
		fmt.Printf("%v", n.Data)
		if n.Left != nil || n.Right != nil {
			fmt.Printf("( ")
			PrintBT(n.Left)
			if n.Right != nil {
				fmt.Printf(",")
			}
			PrintBT(n.Right)
			fmt.Printf(") ")
		}
	}
}

func Depth(n *Node) int {
	var depleft, depright int
	if n == nil {
		return 0
	} else {
		depleft = Depth(n.Left)
		depright = Depth(n.Right)
		if depleft > depright {
			return depleft + 1
		} else {
			return depright + 1
		}
	}
}

func LeafCount(n *Node) int {
	if n == nil {
		return 0
	} else if (n.Left == nil) && (n.Right == nil) {
		return 1
	} else {
		return (LeafCount(n.Left) + LeafCount(n.Right))
	}
}

func PreOrder(n *Node) {
	if n != nil {
		fmt.Printf(" %v ", n.Data)
		PreOrder(n.Left)
		PreOrder(n.Right)
	}
}

func InOrder(n *Node) {
	if n != nil {
		PreOrder(n.Left)
		fmt.Printf(" %v ", n.Data)
		PreOrder(n.Right)
	}
}

func PostOrder(n *Node) {
	if n != nil {
		PreOrder(n.Left)
		PreOrder(n.Right)
		fmt.Printf(" %v ", n.Data)
	}
}

运行结果:

---------二叉树的创建---------
root node( left node( 100,3.14) ,right node) 

---------二叉树的基本操作---------
root node( left node( 100,3.14) ,right node) 
此二叉树的深度为: 3
此二叉树的叶子节点数为: 3

---------二叉树的遍历---------
 root node  left node  100  3.14  right node 
 left node  100  3.14  root node  right node 
 left node  100  3.14  right node  root node