Data Structure-binary tree and Binary Search Tree
PressTree-Binary Search TreeThe order is clearly explained.
I. Tree
A Tree is a finite set of n (n ≥ 0) nodes. In any non-empty tree:
(1) There is only one specific Root node;
(2) When n> 1, the remaining nodes can be divided into m (m> 0) finite sets T1, T2 ,..., Tm, where each set is itself a tree, and is called a root SubTree ).
Node Degree (Degree)The number of subtree owned by a node is called the Degree of the node ). A node with a degree of 0 is called a Leaf or a terminal node. A node with a degree of less than 0 is called a non-terminal node or a branch node.
Tree degree:Is the maximum degree of each node in the tree.
Children and Parents:The root of the subtree of a node is the Child of the node. Correspondingly, the node is called the Child's Parent ).
Node Level ):Is calculated from the root node, the root is the first layer, the root child is the second layer, and so on. The maximum hierarchy of nodes in the tree is called the Depth or height of the tree.
If the Subtrees of the nodes in the tree are regarded as ordered (that is, they cannot be exchanged) from left to right, they are called ordered trees; otherwise, they are called unordered trees.
Binary Tree
A Binary Tree has at most two Subtrees (nodes with a degree greater than 2 in a Binary Tree) and has left and right Subtrees.
The nature of Binary Trees:
(1) At most 2i-1 nodes (I ≥1) on the I layer of a binary tree ).
(2) A binary tree with a depth of k has at most 2k-1 nodes (k ≥ 1 ).
(3) For any binary tree, if the number of terminal nodes is n0 and the number of nodes with the degree of 2 is n2, n0 = n2 + 1.
There are many terminologies about trees. I don't want to explain them too much here, so I don't want to draw any picture. I have found a diagram to illustrate the problem.Path, root, parent node, child node, leaf node, child tree, LayerConcepts
3. Binary Search Tree (left <middle <right)
We start with a special and widely used binary tree: Binary Search Tree.
The nature of the Binary Search Tree:
(1) if its left subtree is not empty, the value of all nodes on the left subtree is smaller than its root node value;
(2) if its right subtree is not empty, the value of all nodes on the right subtree is greater than the value of its root node;
(3) Its left and right subtree are also binary lookup trees.
In a word, the feature of the Binary Search Tree is that the keyword value of the Left subnode of a node is smaller than that of the node, and the keyword value of the right subnode is greater than or equal to that of the parent node.
The basic operation of the Binary Search Tree isSearch, insert, delete, and traverse, Which is described as follows:
1. search)
As we know, the feature of the Binary Search Tree is that the left child node is smaller than the parent node, and the right child node is greater than or equal to the parent node. When searching for a node, start with the root node. If the element value is smaller than the root node, go to the left subnode. Otherwise, go to the right subnode, and so on until the node is found, or if the last leaf node is not found, the node is not found in the tree.
The code is:
/** Find the element and return true */public boolean search (E) {TreeNode
Current = root; // start from the root element while (current! = Null) {if (e. compareTo (current. element) <0) {// if it is smaller than the current element value, it points to the left subtree current = current of the current element. left;} else if (e. compareTo (current. element)> 0) {// if it is greater than the current element value, it points to the right subtree of the current element current = current. right;} else // element is equal to current. element return true; // If an element is found, true is returned.} return false ;}
2. insert)
To insert a new node, you must first determine the insertion location. The key idea is to determine the location of the new node's parent node.
Code:
/** Insert an element. true */public boolean insert (E) {if (root = null) root = createNewNode (e) is returned ); // if the tree is empty, create a heel node else {// mark the current parent node location TreeNode
Parent = null; TreeNode
Current = root; while (current! = Null) if (e. compareTo (current. element) <0) {parent = current; current = current. left;} else if (e. compareTo (current. element)> 0) {parent = current; current = current. right;} else return false; // duplicate nodes cannot be inserted. // create a new node and attach it to the parent node if (e. compareTo (parent. element) <0) parent. left = createNewNode (e); else parent. right = createNewNode (e);} size ++; return true; // insert successful}
3. delete)
Deleting a node in BST is the most troublesome operation. The following two methods are summarized:
Case 1: delete a vertex without a left childThis is to connect the parent node of the node to the child of the current node.
Case2: the deletion vertex has a left child.In this case, first find the rightmost node of the Left subtree of the current node, because the rightmost node of the Left subtree of a node is smaller than the leftmost node of the right subtree, copy the rightmost node to the delete vertex, and then delete the rightmost node.
Code:
/** Return true if the node is deleted successfully. If not in the tree, return false */public boolean delete (E e) {// mark the deleted node and its parent node location as TreeNode
Parent = null; TreeNode
Current = root; while (current! = Null) {if (e. compareTo (current. element) <0) {parent = current; current = current. left;} else if (e. compareTo (current. element)> 0) {parent = current; current = current. right;} else break; // The element is in this tree} if (current = null) return false; // The element is not in the tree if (current. left = null) {// first case: the element does not have a left subtree, direct the right subtree of the current node to the right subtree of its parent node // directly link the right subtree of the current node to the right subtree of its parent node if (parent = null) {root = current. right;} else {if (e. compareTo (parent. element) <0) parent. left = current. right; else parent. right = current. right ;}} else {// Case 2: The element has a left subtree, first, find the rightmost node of the Left subtree of the current node // The parent node and rightmost node TreeNode of the Left subtree of the current node
ParentOfRightMost = current; TreeNode
RightMost = current. left; // always to the right, find the rightMost node, because the rightMost node of the left subtree of a node is smaller than the leftmost node of the right subtree while (rightMost. right! = Null) {parentOfRightMost = rightMost; rightMost = rightMost. right; // always to the right}/** the above Code aims to find the rightmost node of the Left subtree for deleting a node, because the rightmost node of the Left subtree of a node is smaller than the leftmost node of the right subtree * // find the rightmost node and put it to the current location to be deleted. element = rightMost. element; // remove the rightmost node if (parentOfRightMost. right = rightMost) parentOfRightMost. right = rightMost. left; // put the left subtree of the rightmost node on the right subtree of its parent node, else // details: parentOfRightMost = current parentOfRightMost. left = rightMost. left;} size --; return true; // deletion successful}
The following describes the composition of Binary Trees:
Tree. java
Package com.hust.cn; public interface Tree
> {// Search for the public boolean search (E) element; // insert the public boolean insert (e) element; // delete the public boolean delete (E) element ); // traverse public void inorder () in the middle order; // traverse public void postorder () in the back order; // traverse public void preorder () in the front order (); // return public int getSize (); // empty public boolean isEmpty (); // return tree iterator public java. util. iterator iterator ();}
AbstractTree. java
Package com.hust.cn; public abstract class AbstractTree
> Implements Tree
{// Traverse public void inorder () {}// traverse public void postorder () {}// traverse public void preorder () in the forward order () {} // empty public boolean isEmpty () {return getSize () = 0;} // return tree iterator public java. util. iterator iterator () {return null ;}}
BinaryTree. java
Package com.hust.cn; public class BinaryTree
> Extends AbstractTree
{Protected TreeNode
Root; // node class, which is an internal class protected int size = 0;/** constructor */public BinaryTree () {}/** create a binary search tree for the object array */public BinaryTree (E [] objects) {for (int I = 0; I <objects. length; I ++) insert (objects [I]);}/** query element, returns true */public boolean search (E e) {TreeNode
Current = root; // start from the root element while (current! = Null) {if (e. compareTo (current. element) <0) {// if it is smaller than the current element value, it points to the left subtree current = current of the current element. left;} else if (e. compareTo (current. element)> 0) {// if it is greater than the current element value, it points to the right subtree of the current element current = current. right;} else // element is equal to current. element return true; // If an element is found, return true} return false;}/** insert an element. If the element is successfully inserted, return true */public boolean insert (E) {if (root = null) root = createNewNode (e); // if the tree is empty, create an else with the node {// mark the current parent node location TreeNode
Parent = null; TreeNode
Current = root; while (current! = Null) if (e. compareTo (current. element) <0) {parent = current; current = current. left;} else if (e. compareTo (current. element)> 0) {parent = current; current = current. right;} else return false; // duplicate nodes cannot be inserted. // create a new node and attach it to the parent node if (e. compareTo (parent. element) <0) parent. left = createNewNode (e); else parent. right = createNewNode (e);} size ++; return true; // insert successful}/* Create a new node */protected TreeNode
CreateNewNode (E e) {return new TreeNode
(E);}/** sequential traversal */public void inorder () {inorder (root);}/** sequential traversal from the root node, recursive Method */protected void inorder (TreeNode
Root) {if (root = null) return; inorder (root. left); System. out. print (root. element + ""); inorder (root. right);}/** back-order traversal */public void postorder () {postorder (root);}/** traverse from the back-order of the root node, recursive Method */protected void postorder (TreeNode
Root) {if (root = null) return; postorder (root. left); postorder (root. right); System. out. print (root. element + "");}/** pre-order traversal */public void preorder () {preorder (root);}/** pre-order traversal from the root node, recursive Method */protected void preorder (TreeNode
Root) {if (root = null) return; System. out. print (root. element + ""); preorder (root. left); preorder (root. right);}/** return tree size */public int getSize () {return size;}/** return root node */public TreeNode getRoot () {return root;}/** return the path from the root node to a specific element */public java. util. arrayList
> Path (E) {java. util. ArrayList
> List = new java. util. ArrayList
> (); // Use an array to store the TreeNode element in the path
Current = root; // start from the root node while (current! = Null) {list. add (current); // add the current element to the array if (e. compareTo (current. element) <0) {current = current. left;} else if (e. compareTo (current. element)> 0) {current = current. right;} else break;} return list; // return node array}/** delete a node. If the node is deleted successfully, true is returned, false */public boolean delete (E) not returned in the tree {// mark the deleted node and the parent node location of the node TreeNode
Parent = null; TreeNode
Current = root; while (current! = Null) {if (e. compareTo (current. element) <0) {parent = current; current = current. left;} else if (e. compareTo (current. element)> 0) {parent = current; current = current. right;} else break; // The element is in this tree} if (current = null) return false; // The element is not in the tree if (current. left = null) {// first case: the element does not have a left subtree, direct the right subtree of the current node to the right subtree of its parent node // directly link the right subtree of the current node to the right subtree of its parent node if (parent = null) {root = current. right;} else {if (e. compareTo (parent. element) <0) parent. left = current. right; else parent. right = current. right ;}} else {// Case 2: The element has a left subtree, first, find the rightmost node of the Left subtree of the current node // The parent node and rightmost node TreeNode of the Left subtree of the current node
ParentOfRightMost = current; TreeNode
RightMost = current. left; // always to the right, find the rightMost node, because the rightMost node of the left subtree of a node is smaller than the leftmost node of the right subtree while (rightMost. right! = Null) {parentOfRightMost = rightMost; rightMost = rightMost. right; // always to the right}/** the above Code aims to find the rightmost node of the Left subtree for deleting a node, because the rightmost node of the Left subtree of a node is smaller than the leftmost node of the right subtree * // find the rightmost node and put it to the current location to be deleted. element = rightMost. element; // remove the rightmost node if (parentOfRightMost. right = rightMost) parentOfRightMost. right = rightMost. left; // put the left subtree of the rightmost node on the right subtree of its parent node, else // details: parentOfRightMost = current parentOfRightMost. left = rightMost. left;} size --; return true; // deletion successful}/** get the central iterator */public java. util. iterator iterator () {return inorderIterator ();}/** create an Iterator class */public java. util. iterator inorderIterator () {return new InorderIterator ();} // class of the Middle-order Iterator, class of the internal class InorderIterator implements java. util. iterator {// array of storage elements private java. util. arrayList
List = new java. util. ArrayList
(); Private int current = 0; // the position of the current element in the array public InorderIterator () {inorder (); // traverse Binary Tree in ascending order}/** traverse tree in descending order from the root */private void inorder () {inorder (root );} /** traverse the subtree in ascending order */private void inorder (TreeNode
Root) {if (root = null) return; inorder (root. left); list. add (root. element); inorder (root. right);}/** traverse the next element */public boolean hasNext () {if (current <list. size () return true; return false;}/** get the current element, and point the pointer to another element */public Object next () {return list. get (current ++);}/** remove current element */public void remove () {delete (list. get (current); // Delete the current element list. clear (); // clear the array inorder (); // re-traverse the array in the middle order}/** clear all elements of the tree */public void clear () {root = null; size = 0;}/** internal class, tree node class */public static class TreeNode
> {E element; TreeNode
Left; TreeNode
Right; public TreeNode (E e) {element = e ;}}}
TestBinaryTree. java
Package com.hust.cn; public class TestBinaryTree {public static void main (String [] args) {// create a binary search tree BinaryTree
Tree = new BinaryTree
(); Tree. insert ("George"); tree. insert ("Michael"); tree. insert ("Tom"); tree. insert ("Adam"); tree. insert ("Jones"); tree. insert ("Peter"); tree. insert ("Daniel"); // traverses the tree System. out. println ("Inorder (sorted):"); tree. inorder (); System. out. println ("\ nPostorder:"); tree. postorder (); System. out. println ("\ nPreorder:"); tree. preorder (); System. out. println ("\ nThe number of nodes is" + tree. getSize ());// Find an element System. out. println ("\ nIs Peter in the tree? "+ Tree. search ("Peter"); // a path from root to peter: System. out. println ("\ nA path from the root to Peter is:"); java. util. arrayList
> Path = tree. path ("Peter"); for (int I = 0; path! = Null & I <path. size (); I ++) System. out. print (path. get (I ). element + ""); // construct a binary search tree using arrays and traverse Integer [] numbers = {2, 4, 3, 1, 8, 5, 6 in the middle order, 7}; BinaryTree
IntTree = new BinaryTree
(Numbers); System. out. println ("\ nInorder (sorted):"); intTree. inorder ();}}
Test results: