Binary tree (1)-overview (with binary search tree implementation)

Trees and graphs are typical non-linear data structures

Definition of
tree : A tree is a finite set of n (n>=0) nodes. When n=0, it becomes an empty tree. In any non-empty tree, it has the following characteristics:

  1. Only one specific node becomes the root node
  2. When n>1, the remaining nodes can be divided into m (m>0) irrelevant finite sets. Each set is also a tree and becomes a subtree of the root.
树的最大层级数,称为树的高度或者深度

The definition of a
binary tree : a binary tree refers to该树的每个节点最多有2个子节点,有可能时两个,也可能只有1个,或者是没有

Two special forms of binary trees:

满二叉树:一个二叉树的所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上,这个树就是满二叉树
完全二叉树:一个二叉树的`最后一个节点之前`所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上

The physical storage structure of the binary tree

1. Chain storage structure

Using the storage structure of the linked list, each node of the binary tree contains 3 parts

  • Data variable to store data
  • Left pointer to the left child
  • Right pointer to the right child

2. Array

When using array storage, the nodes of the binary tree are placed in the corresponding positions in the array according to the hierarchical order. If the left or right child of a node is vacant, the corresponding position of the array is also vacant

Why is it designed like this? Because this can easily locate the child nodes and parent nodes of the binary tree in the array

Assuming that the subscript of a parent node is parent, then the subscript of its left child node is 2 parent+1, and the subscript of the right child node is 2 parent+2.

in turn. Assuming that the subscript of a left child node is leftchild, then its parent node subscript is (leftchild-1)/2

显然,对于一个稀疏的二叉树来说,用数组表示法是非常浪费空间的。
然而因为完全二叉树的特殊性,用数组来存储是非常合适的,比如二叉堆,一种特殊的完全二叉树

Application of Binary Tree

There are many forms of binary trees, in addition to general binary trees, from the above-mentioned full binary trees, complete binary trees, and binary heaps, etc.

So what are the functions of so many kinds of binary trees?

  1. Used for search operations
  2. Maintain relative order between elements

Binary search tree

Also known as binary sort tree, binary search tree and so on. As the name implies, there is a certain order among the elements of this binary tree, and it is easy to find

definition:

  1. If the left subtree is not empty, then左子树上所有节点的值均小于根节点的值
  2. If the right subtree is not empty, then右子树上所有节点的值均大于根节点的值
  3. The left subtree and the right subtree are also binary search trees
  4. 没有键值相等的结点

Here we use definition 1. There are three definitions ( binary search tree Baidu Encyclopedia ) that are correct, and you need to choose according to different needs during development.

Golang implements a binary search tree:

package main

import "fmt"

// 二叉树
type BinaryTree struct {
    
    
	HeadNode *TreeNode
}

//二叉树节点
type TreeNode struct {
    
    
	Data   int32     // 链表上的数据
	Left   *TreeNode // 指针指向左孩子节点
	Right  *TreeNode // 指针指向右孩子节点
}

// 判断二叉树是否为空树,只需要判断第一个元素是否是 nil
func (self *BinaryTree) IsEmpty() bool {
    
    
	if self.HeadNode == nil {
    
    
		return true
	} else {
    
    
		return false
	}
}

// 在二叉查找树里添加数据
func (self *BinaryTree) Add(value int32) bool {
    
    
	neWNode := &TreeNode{
    
    Data: value,}
	node := self.HeadNode
	if node == nil {
    
    
		self.HeadNode = neWNode
		return true
	}
	for node.Data!=value {
    
    
		if value < node.Data {
    
    
			if node.Left!=nil{
    
    
				node = node.Left
			}else {
    
    
				node.Left=neWNode
				return true
			}
		}
		if value > node.Data {
    
    
			if  node.Right!=nil{
    
    
				node = node.Right
			}else {
    
    
				node.Right=neWNode
				return true
			}
		}
	}
	return false
}

// 查找元素所在的节点
func (self *BinaryTree) Get(value int32) *TreeNode {
    
    
	node := self.HeadNode
	for node != nil {
    
    
		if value < node.Data {
    
    
			node = node.Left
		} else if value > node.Data {
    
    
			node = node.Right
		} else {
    
    
			return node
		}
	}
	return nil
}

func NewBinaryTree() BinaryTree {
    
    
	BinaryTree := BinaryTree{
    
    HeadNode: nil}
	return BinaryTree
}

func main() {
    
    
	binaryTree := NewBinaryTree()
	fmt.Println(binaryTree.IsEmpty())
	fmt.Println(binaryTree.Add(3))
	fmt.Println(binaryTree.Add(3))
	fmt.Println(binaryTree.Add(2))
	fmt.Println(binaryTree.Add(4))
	fmt.Println(binaryTree.HeadNode.Data)
	fmt.Println(binaryTree.HeadNode.Right.Data)
	fmt.Println(binaryTree.HeadNode.Left.Data)
	fmt.Println(binaryTree.Get(4).Data)
	fmt.Println(binaryTree.IsEmpty())
}

Time complexity of binary search tree:

For a binary search tree with relatively balanced node distribution, if the total number of nodes is n, the time complexity of searching for nodes is O(logn), which is the same as the depth of the tree.
This method of searching step by step by comparing the size is very similar to the binary search algorithm

But for extreme cases (the data size is increased or decreased each time the data is inserted), there is only half the tree in appearance, and the search time complexity will degenerate to O(n)

To solve this problem, it involves the self-balancing of the binary tree, which will be introduced later.

Guess you like

Origin blog.csdn.net/csdniter/article/details/109788469