A binary tree structure is a dynamic structure that can grow to any size. It has two pointers in each node, known as the left and right pointers as this is the way that trees are generally drawn.
Nodes in a binary tree are defined in the following way:
type
datatype=string;
treepointer=^treenode;
treenode=record
dataitem:datatype;
leftchild, rightchild: treepointer;
end;
The datatype in this model can be easily changed and further data fields could be added to the record.
When items are inserted into a tree the approach followed is to place items less than the current data item in the next left hand node and items greater than the current data item in the next right hand node. If a node is full this rule is applied again in a recursive fashion.
Thus if 'p' is inserted into an empty tree it can be represented as:
p
/
\
nil
nil
If 'a' is added the tree becomes:
p
/
\
a
nil
If 'b' is added the tree becomes
p
/
\
a
nil
\
b
If 's' is added the tree becomes
p
/ \
a
s
\
b
And so on.
When data has been entered the tree may be traversed in one of three main ways:
An in-order traversal of the tree above is: a b p s
A pre-order traversal of this tree is: p a b s
A post-order traversal of this tree is: b a s p
You should check these patterns for yourself and also verify that the program produces correct results.
Programming a binary tree is not as hard as it might seem, once the recursive nature of the structure is understood. To insert an item into a tree we must look for an empty node, calling the insert procedure recursively until one is found:
procedure TForm1.Button1Click(Sender: TObject);
procedure insertitem(var rootpointer: treepointer; item:datatype);
begin
if rootpointer=nil then //new empty tree node
begin
new(rootpointer);
with rootpointer^ do
begin
dataitem:=item;
leftchild:=nil;
rightchild:=nil;
end;
end
else
if item < rootpointer^.dataitem then
insertitem(rootpointer^.leftchild, item)
else
insertitem(rootpointer^.rightchild, item);
end;
begin
insertitem(rootpointer, edit1.text);
edit1.Text:='';
edit1.SetFocus;
end;
Variables are declared in either the public section of the class or in the var section immediately after it:
Form1: TForm1;
rootpointer:treepointer;
item:datatype;
traversal:string;
To traverse a tree in the sorted order of the items:
procedure TForm1.Button2Click(Sender: TObject);
procedure inorder(rootpointer:treepointer);
begin
if not (rootpointer = nil) then
with rootpointer^ do
begin
inorder(leftchild); //these three
instructions do the business
traversal:=traversal+dataitem +' ';
inorder(rightchild)
end;
end;
begin
traversal:='';
inorder(rootpointer);
memo1.Text:=traversal;
end;
To perform the pre-order traversal we only need to change the order of the three instructions in the respective procedures:
procedure TForm1.Button3Click(Sender: TObject);
procedure preorder(rootpointer:treepointer);
begin
if not (rootpointer = nil) then
with rootpointer^ do
begin
traversal:=traversal+dataitem +' '; //these
three instructions are put in different order
preorder(leftchild);
preorder(rightchild)
end;
end;
begin
traversal:='';
preorder(rootpointer);
memo2.Text:=traversal;
end;
procedure TForm1.Button4Click(Sender: TObject);
procedure postorder(rootpointer:treepointer);
begin
if not (rootpointer = nil) then
with rootpointer^ do
begin
postorder(leftchild); //these three
instructions are put in different order
postorder(rightchild);
traversal:=traversal+dataitem +' ';
end;
end;
begin
traversal:='';
postorder(rootpointer);
memo3.Text:=traversal;
end;
Each of the traversals is a variation on the others and each one is recursive, visiting the nodes and outputting the results according to the requirements of the traversal.
We can add a routine to clear the tree and the displays:
procedure TForm1.Button6Click(Sender: TObject);
begin
rootpointer:=nil;
memo1.Clear;
memo2.clear;
memo3.clear;
end;
Here is a possible implementation with items entered in order: nigel, ann, kate, mary, suzanne, david:
