1. What is a tree

What is a tree?

Tree

A tree is a connected simple graph with no simple cycles.

  • In a tree, there is a unique simple path between any two of its vertices.
  • If we add an edge to a tree, it creates a cycle.
  • If we remove an edge from a tree, it becomes not connected.
graph G {
	layout=neato
	node[shape=point]
	4--1,2,3,5
	5--6,7,8
	8--9,10,11
}
Link to original

Link to original

3. Applications of trees

Applications of trees

Trees can be used for modelling and problem solving.

  • Family trees in genealogy
  • Representing organisations
  • Computer file systems
  • Constructing efficient methods for locating items in a list Binary search trees
  • Game trees to analyse winning strategies in games
  • Decision trees
  • Decomposition trees to parse arithmetical and logic formulas and expressions
Link to original

5. Special trees

Special Trees

A rooted tree is called an -ary tree if every internal vertex has no more than children.

A rooted tree is called a full -ary tree if every internal vertex has exactly children.

Binary Trees

A rooted tree is called a full binary tree if every internal vertex has exactly children: a left child and a right child

graph G {
	label="full binary tree"
	node[shape="point"]
	
	1--2,3
	2--4,5
	5--6,7
}

When we have a full binary tree of height :

  • the left and right subtrees of the root are both full binary trees of height
  • at least one of the left and right subtrees of the root is a full binary tree of height

Counting vertices and edges of trees

A full binary tree with internal vertices contains vertices altogether. Every vertex, except the root, is the child of an internal vertex. Because each of the internal vertices has children, there are vertices in the tree other than the root.

A full -ary tree with internal vertices contains vertices altogether. Every vertex, except the root, is the child of an internal vertex. Because each of the internal vertices has children, there are vertices in the tree other than the root.

Link to original

7. Decomposition trees

Decomposition Trees

We can represent complicated expressions, like formulas of propositional logic and arithmetical expressions using rooted trees.

For example we can represent the formula as:

graph G {
	graph [nodesep="0.6"]
	node[shape=plain]
 
	r[label="↔"]
	1[label="¬"]
	2[label="∧"]
	3[label="p"]
	4[label="q"]
	5[label="∨"]
	6[label="¬"]
	7[label="¬"]
	8[label="q"]
	9[label="p"]	
	
	r--1,5
	1--2
	2--3,4
 
	5--6,7
	6--9
	7--8
}

Notice subgraphs here represent parts of the equation:

graph G {
	graph [nodesep="1"]
	node[shape=plain]
 
	r[label="↔"]
	1[label="¬"]
	2[label="∧"]
	3[label="p"]
	4[label="q"]
	5[label="∨"]
	6[label="¬"]
	7[label="¬"]
	8[label="q"]
	9[label="p"]	
	
	r--1,5
	
	subgraph cluster0 {
		label="¬(p∧q)"
		1--2
		
		subgraph cluster2 {
			label="p∧q"
			2--3,4
		}
	}
	
	subgraph cluster1 {
		label="¬p∨¬q"
		5--6,7
		
		subgraph cluster3 {
			label="¬p"
			6--9
		}
		
		subgraph cluster4 {
			label="¬q"
			7--8
		}
	}
}
Link to original

8. Linearly ordered lists

Linearly ordered lists

Linearly ordered list

Linearly ordered list is a sequence whose elements are linearly ordered (linear order), which is not necessarily the order of listing.

For example:

  • A list of natural numbers can be ordered by the relation.
  • A list of words can be ordered by the lexicographical order relation, . As below.
Link to original

Searching for items in a linearly ordered list is important and Binary search trees are particularly useful in representing elements in such a list. There are very efficient methods for:

  • searching for data in binary search trees
  • revising data in binary search trees
  • converting linaerly ordered lists to binary search trees and back
title: Example: lexicographical order on words
First, we order the letters of the English alphabet as usual:
 
$$
	a \prec b \prec c \prec d \prec e \prec ... \prec x \prec y \prec z
$$
 
Then, we can use this ordering of the letters to order longer words:
- Given two words $w_1$ and $w_2$, we compare them letter by letter, from left to right, passing equal letters.
- If at any point a letter in $w_1$ is $\prec$-smaller than the corresponding letter in $w_2$, then we put $w_1 \prec w_2$.
- If every letter in $w_1$ is equal to the corresponding letter in $w_2$ but $w_2$ is longer than $w_1$, then we also put $w_1 \prec w_2$.
- In any other case, we put $w_2 \prec w_1$.
 
$$
	\text{discreet} \prec \text{discreetness} \prec \text{discrete} \prec \text{discretion} \prec \text{geography}
$$
$$
	 \prec \text{geology} \prec \text{mathematics} \prec \text{physics} \prec \text{psychology}
	 $$
Link to original

9. Binary search trees

Binary search trees

Given two things: a list of items and a linear order on them. A binary search tree for and is a binary tree in which every vertex is labelled with an item from such that we have:

  1. the label of each vertex:
    • is -greater than the labels of all vertices in the left subtree
    • is -less than the labels of all vertices in its right subtree
  2. every path in the tree be compatible with the order of listing:
    graph G {
     layout=neato
    	node[shape=point]
     
     a[xlabel="5" pos="2,4!"]
     b[xlabel="3" pos="1,3!"]
     c[xlabel="128" pos="3,3!"]
     d[xlabel="2" pos="0.5,2!"]
     e[xlabel="4" pos="1.5,2!"]
     f[xlabel="15" pos="2.5,2!"]
     g[xlabel="20" pos="3,1!"]
     
     a--b,c
     b--d,e
     c--f
     f--g
    }
    For the list and linear order .

Binary Tree from Linearly ordered list

We are given a list of items, and a linear order on them. We go through each member of the list, from left to right:

  • First item: becomes our root
  • Comparing: We take the next item in the list, and first compare it with the labels of the ‘old’ vertices already in the list, starting from the root then:
    • moving to the left: if the new item is -less than the label of the respective ‘old’ vertex, if this ‘old’ vertex has a left child, or:
    • moving to the right: if the new item is -greater than the label of the respective ‘old’ vertex, if this ‘old’ vertex has a right child.
  • Adding:
    • When the new item is -less than the label of an ‘old’ vertex and the vertex has no left child, insert a new left child to the ‘old’ vertex and label it with the new item.
    • When the new item is -larger than the label of an ‘old’ vertex and the vertex has no child, then we insert a new right child to the ‘old’ vertex and label it with the new item.

Example BST

Build a binary search tree for the following list of words using the lexicographical order .

  1. Take mathematics and label the root with it:
    graph G {
    	m[shape=point xlabel=mathematics]
    }
  2. We take physics and compare it with mathematics, , mathematics has no right child so we label a new right child with physics:
    graph G {
    	layout=neato
     node[shape=point]
    	m[xlabel=mathematics pos="0,0!"]
     p[xlabel=physics pos="1,-1!"]
     
     m--p
    }
  3. We take geography, , mathematics has no left child so we create a new left child with geography:
    graph G {
    	layout=neato
     node[shape=point]
    	m[xlabel=mathematics pos="0,0!"]
     p[xlabel=physics pos="1,-1!"]
     g[xlabel=geography pos="-1,-1!"]
     
     m--p,g
    }
  4. We take zoology, , so we move to the right child of the root and take the label, which in this case is physics.
  5. We now compare zoology with physics, , physics has no right child, hence we label a new right child:
    graph G {
    	layout=neato
     node[shape=point]
    	m[xlabel=mathematics pos="0,0!"]
     p[xlabel=physics pos="1,-1!"]
     g[xlabel=geography pos="-1,-1!"]
     z[xlabel=zoology pos="1.5,-2!"]
     
     m--p,g
     p--z
    }
  6. We take meteorology, , so we move to the right child of the root and take the label, which in this case is physics.
  7. We now compare zoology with physics, , physics has no left child, hence we label a new left child:
    graph G {
    	layout=neato
     node[shape=point]
    	m[xlabel=mathematics pos="0,0!"]
     p[xlabel=physics pos="1,-1!"]
     g[xlabel=geography pos="-1,-1!"]
     z[xlabel=zoology pos="1.5,-2!"]
     2[xlabel=meteorology pos="0.5,-2!"]
     
     m--p,g
     p--z,2
    }
  8. We take geology, , so we move to the left child of the root and take the label, which in this case is geography.
  9. We now compare geology with geography, , physics has no right child, hence we label a new right child:
    graph G {
    	layout=neato
     node[shape=point]
    	m[xlabel=mathematics pos="0,0!"]
     p[xlabel=physics pos="2,-1!"]
     g[xlabel=geography pos="-2,-1!"]
     z[xlabel=zoology pos="2.5,-2!"]
     2[xlabel=meteorology pos="1.5,-2!"]
     3[xlabel=geology pos="-1.5,-2!"]
     
     m--p,g
     p--z,2
     g--3
    }
  10. Finally, we take psychology, compare it with mathematics, move to the right, compare it with physics, move to the right then compare it with zoology, , hence create a new left child:
    graph G {
    	layout=neato
     node[shape=point]
    	m[xlabel=mathematics pos="0,0!"]
     p[xlabel=physics pos="2,-1!"]
     g[xlabel=geography pos="-2,-1!"]
     z[xlabel=zoology pos="2.5,-2!"]
     2[xlabel=meteorology pos="1.5,-2!"]
     3[xlabel=geology pos="-1.5,-2!"]
     4[xlabel=psychology pos="2,-3!"]
     
     m--p,g
     p--z,2
     g--3
     z--4
    }

Say we had to add a new word, chemistry, to our BST. How many comparisons do we need to locate or find it?

In this case, it’s just . We compare it with mathematics, move left, compare it with geography. As and geography has no left child, we know that chemistry is not in the tree. We can create a new left child and label it as such.

graph G {
	layout=neato
	node[shape=point]
	m[xlabel=mathematics pos="0,0!"]
	p[xlabel=physics pos="2,-1!"]
	g[xlabel=geography pos="-2,-1!"]
	z[xlabel=zoology pos="2.5,-2!"]
	2[xlabel=meteorology pos="1.5,-2!"]
	3[xlabel=geology pos="-1.5,-2!"]
	5[label=chemistry pos="-2.5,-2!" shape="plain"]
	4[xlabel=psychology pos="2,-3!"]
 
	m--p,g
	p--z,2
	g--3
	z--4
	g--5
 
	subgraph cluster0 {
		5
	}
}
Link to original

10. Tree traversal algorithms

Tree traversal

Rooted trees are often used to store information. We use different systematic approaches to visit each vertex of a rooted tree to access data, called traversal algorithms.

Common traversal algorithms:

  • Preorder traversal: visit the root, continue traversing subtrees in preorder, from left to right
  • Inorder traversal: begin traversing leftmost subtree inorder, then visit root, then continue traversing subtrees in inorder, from left to right
  • Postorder traversal: begin traversing leftmost subtree in postorder, then continue traversing subtrees in postorder, from left to right, finally visit root

Link to original