Introduction
In Computer Science, a binary tree is a hierarchical structure of nodes, each node referencing at most to two child nodes. Every binary tree has a root from which the first two child nodes originate. If a node has no children, then such nodes are usually termed leaves, and mark the extent of the tree structure.
A particular kind of binary tree, called the binary search tree, is very useful for storing data for rapid access, storage, and deletion. Data in a binary search tree are stored in tree nodes, and must have associated with them an ordinal value or key; these keys are used to structure the tree such that the value of a left child node is less than that of the parent node, and the value of a right child node is greater than that of the parent node. Sometimes, the key and datum are one and the same. Typical key values include simple integers or strings, the actual data for the key will depend on the application. In this article, I describe a binary search tree that stores string/double pairs. That is, the key is the string value and the data associated with the key is a double value. Developers can search the tree using string values.
Background
There are a number of basic operations one can apply to a binary search tree, the most obvious include, insertion, searching, and deletion.
To insert a new node into a tree, the following method can be used. We first start at the root of the tree, and compare the ordinal value of the root to the ordinal value of the node to be inserted. If the ordinal values are identical, then we have a duplicate and we return to the caller indicating so. If the ordinal value is less than the root, then we follow the left branch of the root, else we follow the right branch. We now start the comparison again but at the branch we took, comparing the ordinal value of the child with the node to be inserted. Traversal of the tree continues in this manner until we reach a left or right node which is empty and we can go no further. At this point, we insert the new node into this empty location. Note that new nodes are always inserted as leaves into the tree, and strictly speaking, nodes are thus appended rather than inserted.
Searching a binary search tree is almost identical to inserting a new node except that we stop the traversal when we find the node we're looking for (during an insertion, this would indicate a duplicate node in the tree). If the node is not located, then we report this to the caller.
Both insertion and searching are naturally recursive and are, arguably, easier to understand when considered in terms of their unit operation. A basic recursive search algorithm will look like:
Collapse
|
Copy Code
node search (node, key) {
if node is null then return null;
if node.key = key then
if key < node then
return node
return search (node.left, key);
else
return search (node.right, key);
In the source code provided with this article, insertion is implemented recursively, while searching uses an iterative approach.
Deletion is a little bit more complicated but boils down to three rules. The three rules refer to deleting nodes without any children, nodes with one child, and nodes with two children. If a node has no children, then the node is simply deleted. If the node has one child, then the node is deleted and the child node is brought forward to link to the parent. The complication occurs when a node has two children. However, even here, the rules are straightforward when stated. To delete a node with two children, the next ordinal node (called the successive node) on the right branch is used to replaced the deleted node. The successive node is then deleted. The successive node will always be the left most node on the right branch (likewise, the predecessor node will be the right most node on the left branch). The figure below illustrates the deletion rules.
A common alternative to using binary search tree is to use Hash tables. Hash tables have better search and insertion performance metrics. In theory, the time it takes to insert or search for an item in a Hash table is independent of the number of data items stored. In contrast, a binary search tree scales with log (N) where N is the number of data items (still far better than a linear search). The .NET libraries contain explicit support for Hash tables.
Balanced Trees
The time taken to insert or search for a specific item in a tree will be affected by a tree's depth. Deep trees take longer to search, and the insertion order into a tree can affect a tree's shape. A random insertion order will generally produce a more bushy and hence shallower tree compared to an ordered insert. Bushy trees are often called balanced trees, and although not implemented here, balancing a tree is a highly desirable feature for a binary search tree implementation. Certain algorithms such as the red-black tree will auto-balance as the tree is constructed (see Red/Black tree animation). The figure below shows three trees generated by three identical data sets but inserted in a different order. The first is the most balanced and hence the most shallow of the three examples.
Implementing the search and insertion methods using a recursive approach has the potential to yield poor performance, particularly when the trees are unbalanced.
Using the Code
Using the source code provided with this article is very easy. The following code illustrates the instantiation of a new binary tree, the insertion of data into the tree, and subsequent retrieval. The method insert()
is used to insert new data, and the method findSymbol()
is used to locate and retrieve data. If findSymbol()
fails to locate the data item, it returns null
. When successful, findSymbol()
returns a TTreeNode
object which has two properties, name
and value
. The following code illustrates how to use the binary search tree. The class name of the binary tree isTBinarySTree
, and the individual nodes have class type TTreeNode
.
Collapse
|
Copy Code
//
Create a new binary tree
bt =
new
TBinarySTree();
//
Insert data
bt.insert (
"
Canis Minoris"
,
5
.
37
);
bt.insert (
"
Gamma Cancri"
,
4
.
66
);
bt.insert (
"
Phi Centauri"
,
3
.
83
);
bt.insert (
"
Kappa Tauri"
,
4
.
21
);
//
Retrieve data
TTreeNode symbol = bt.findSymbol (
"
Phi Centauri"
);
if
(symbol !=
null
)
Console.WriteLine (
"
Star {1} has magnitude = {0}"
, symbol.name, symbol.value);
Other methods of interest include:
Collapse
|
Copy Code
bt.clear();
bt.count();
count
returns the number of nodes in the tree.
Collapse
|
Copy Code
bt.delete (key);
delete
will delete the node with the given key. If the method fails to locate the node, the method throws a simple exception.
The source code is licensed under the BSD license. The source should compile on C# 2.0.
To use the source code, unpack the source, load the binary tree solution (binaryTree.sln) and compile the BinaryTree project. In your own project, include as a reference to BinaryTree.dll. This version was written using Visual Studio 2003.
http://www.codeproject.com/Articles/18976/A-simple-Binary-Search-Tree-written-in-C
C# – Tree Sort – In-order traversal of a binary search tree
February 16, 2012
A tree sort is a sort algorithm that builds a binary search tree from the keys to be sorted, and then traverses the tree (in-order) so that the keys come out in sorted order. Its typical use is when sorting the elements of a stream from a file. Several other sorts would have to load the elements to a temporary data structure, whereas in a tree sort the act of loading the input into a data structure is sorting it.
Adding one item to a binary search tree is on average an O(log(n)) process, so adding n items is an O(n log(n)) process, making Tree Sort a so-called, ‘fast sort’. But adding an item to an unbalanced binary tree needs O(n) time in the worst-case, when the tree resembles a linked list (degenerate tree), causing a worst case of O(n2) for this sorting algorithm. The worst case scenario then is triggered by handing a Tree Sort algorithm an already sorted set. This would make the time needed to insert all elements into the binary tree O(n2). The dominant process in the Tree Sort algorithm is the “insertion” into the binary tree, assuming that the time needed for retrieval is O(n).
The worst-case behaviour can be improved upon by using a self-balancing binary search tree. Using such a tree, the algorithm has an O(n log(n)) worst-case performance, thus being degree-optimal. – Wikipedia
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
using System;
using System.Collections.Generic;
using System.Text;
namespace TreeSort
{
class
Node
{
public
int
item;
public
Node leftChild;
public
Node rightChild;
public
void
displayNode()
{
Console.Write(
"["
);
Console.Write(item);
Console.Write(
"]"
);
}
}
class
Tree
{
public
Node root;
public
Tree()
{ root =
null
; }
public
Node ReturnRoot()
{
return
root;
}
public
void
Insert(
int
id)
{
Node newNode =
new
Node();
newNode.item = id;
if
(root ==
null
)
root = newNode;
else
{
Node current = root;
Node parent;
while
(
true
)
{
parent = current;
if
(id < current.item)
{
current = current.leftChild;
if
(current ==
null
)
{
parent.leftChild = newNode;
return
;
}
}
else
{
current = current.rightChild;
if
(current ==
null
)
{
parent.rightChild = newNode;
return
;
}
}
}
}
}
public
void
Preorder(Node Root)
{
if
(Root !=
null
)
{
Console.Write(Root.item +
" "
);
Preorder(Root.leftChild);
Preorder(Root.rightChild);
}
}
public
void
Inorder(Node Root)
{
if
(Root !=
null
)
{
Inorder(Root.leftChild);
Console.Write(Root.item +
" "
);
Inorder(Root.rightChild);
}
}
public
void
Postorder(Node Root)
{
if
(Root !=
null
)
{
Postorder(Root.leftChild);
Postorder(Root.rightChild);
Console.Write(Root.item +
" "
);
}
}
}
class
Program
{
static
void
Main(string[] args)
{
Tree theTree =
new
Tree();
theTree.Insert(
42
);
theTree.Insert(
25
);
theTree.Insert(
65
);
theTree.Insert(
12
);
theTree.Insert(
37
);
theTree.Insert(
13
);
theTree.Insert(
30
);
theTree.Insert(
43
);
theTree.Insert(
87
);
theTree.Insert(
99
);
theTree.Insert(
9
);
Console.WriteLine(
"Inorder traversal resulting Tree Sort"
);
theTree.Inorder(theTree.ReturnRoot());
Console.WriteLine(
" "
);
Console.WriteLine();
Console.WriteLine(
"Preorder traversal"
);
theTree.Preorder(theTree.ReturnRoot());
Console.WriteLine(
" "
);
Console.WriteLine();
Console.WriteLine(
"Postorder traversal"
);
theTree.Postorder(theTree.ReturnRoot());
Console.WriteLine(
" "
);
Console.ReadLine();
}
}
}
|
OUTPUT:
About these ads
http://www.codeproject.com/Articles/18976/A-simple-Binary-Search-Tree-written-in-C
http://chinmaylokesh.wordpress.com/2012/02/16/tree-sort-in-order-traversal-of-a-binary-search-tree/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)