Date post: | 17-Jan-2016 |
Category: |
Documents |
Upload: | gavin-hardy |
View: | 223 times |
Download: | 0 times |
1
Trees
• A Quick Introduction to Graphs
• Definition of Trees
• Rooted Trees
• Binary Trees
• Binary Search Trees
2
Introduction to Graphs
• A graph is a finite set of nodes with edges between nodes
• Formally, a graph G is a structure (V,E) consisting of – a finite set V called the set of nodes, and– a set E that is a subset of VxV. That is, E is a set
of pairs of the form (x,y) where x and y are nodes in V
3
Examples of Graphs
• V={1,2,3,4,5}
• E={(1,2), (2,3), (2,4), (4,2), (3,3), (5,4)}
12
5
3
4
When (x,y) is an edge,we say that x is adjacent to y. 1 is adjacent to 2.2 is not adjacent to 1.4 is not adjacent to 3.
4
A “Real-life” Example of a Graph
• V=set of 6 people: John, Mary, Joe, Helen, Tom, and Paul, of ages 12, 15, 12, 15, 13, and 13, respectively.
• E ={(x,y) | if x is younger than y}
John Joe
Mary Helen
Tom Paul
5
Intuition Behind Graphs
• The nodes represent entities (such as people, cities, computers, words, etc.)
• Edges (x,y) represent relationships between entities x and y, such as:– “x loves y”
– “x hates y”
– “x is as smart as y”
– “x is a sibling of y”
– “x is bigger than y”
– ‘x is faster than y”, …
6
Directed vs. Undirected Graphs
• If the directions of the edges matter, then we show the edge directions, and the graph is called a directed graph (or a digraph)
• The previous two examples are digraphs• If the relationships represented by the edges
are symmetric (such as (x,y) is edge if and only if x is a sibling of y), then we don’t show the directions of the edges, and the graph is called an undirected graph.
7
Examples of Undirected Graphs
• V=set of 6 people: John, Mary, Joe, Helen, Tom, and Paul, where the first 4 are siblings, and the last two are siblings
• E ={(x,y) | x and y are siblings}
John Joe
Mary Helen
Tom Paul
8
Definition of Some Graph Related Concepts (Paths)
• A path in a graph G is a sequence of nodes x1, x2, …,xk, such that there is an edge from each node the next one in the sequence
• For example, in the first example graph, the sequence 4, 1, 2, 3 is a path, but the sequence 1, 4, 5 is not a path because (1,4) is not an edge
• In the “sibling-of” graph, the sequence John, Mary, Joe, Helen is a path, but the sequence Helen, Tom, Paul is not a path
9
Definition of Some Graph Related Concepts (Cycles)
• A cycle in a graph G is a path where the last node is the same as the first node.
• In the “sibling-of” graph, the sequence John, Mary, Joe, Helen, John is a cycle, but the sequence Helen, Tom, Paul, Helen is not a cycle
10
Graph Connectivity
• An undirected graph is said to be connected if there is a path between every pair of nodes. Otherwise, the graph is disconnected
• Informally, an undirected graph is connected if it hangs in one piece
Disconnected Connected
11
Graph Cyclicity
• An undirected graph is cyclic if it has at least one cycle. Otherwise, it is acyclic
Disconnected and acyclic Connected and acyclic
Disconnected and cyclic Connected and cyclic
12
Trees
• A tree is a connected acyclic undirected graph. The following are three trees:
1
2
53 11
12
10
98
7
64
13
Rooted Trees
• A rooted tree is a tree where one of the nodes is designated as the root node. (Only one root in a tree)
• A rooted tree has a hierarchical structure: the root on top, followed by the nodes adjacent to it right below, followed by the nodes adjacent to those next, and so on.
14
Example of a Rooted Tree
1
2
53 11
12
10
98
7
64
1
23
10
11
98
4 6
5
7
12Un-rooted tree
Tree rooted with root 1
15
Tree-Related Concepts
• The nodes adjacent to x and below x are called the children of x,and x is called their parents
• A node that has no children is called a leaf
• The descendents of a node are: itself, its children, their children, all the way down
• The ancestors of a node are: itself, its parent, its grandparent, all the way to the root
1
23
10
11
98
4 6
5
7
12
16
Tree-Related Concepts (Contd.)
• The depth of a node is the number of edges from the root to that node.
• The depth (or height) of
a rooted tree is the depth
of the lowest leaf
• Depth of node 10: 3
• Depth of this tree: 4
1
23
10
11
98
4 6
5
7
12
17
Binary Trees
• A tree is a binary tree if every node has at most two children
1
23
10
11
98
4 6
5
7
12
1
3
10
11
98
4 6
5
7
12
Non-binary tree Binary tree
18
Binary-Tree Related Definitions
• The children of any node in a binary tree are ordered into a left child and a right child
• A node can have a left anda right child, a left childonly, a right child only,or no children
• The tree made up of a leftchild (of a node x) and all itsdescendents is called the left subtree of x
• Right subtrees are defined similarly
10
1
3
11
98
4 6
5
7
12
19
Graphical View Binary-tree Nodes
data
left right
In practice, a TreeNode will be shown as a circle where the data is put inside, and the node label(if any) is put outside.
Graphically, a TreeNode is:
5.8 2data label
• A binary-tree node consists of 3 parts:
-Data-Pointer to left child-Pointer to right child
20
A Binary-tree Node Classclass TreeNode { public: typedef int datatype; TreeNode(datatype x=0, TreeNode *left=NULL,
TreeNode *right=NULL){data=x; this->left=left; this->right=right; };
datatype getData( ) {return data;};
TreeNode *getLeft( ) {return left;};
TreeNode *getRight( ) {return right;};void setData(datatype x) {data=x;};void setLeft(TreeNode *ptr) {left=ptr;};void setRight(TreeNode *ptr) {right=ptr;};
private:datatype data; // different data type for other appsTreeNode *left; // the pointer to left childTreeNode *right; // the pointer to right child
};
21
Binary Tree Class
class Tree { public: typedef int datatype; Tree(TreeNode *rootPtr=NULL){this->rootPtr=rootPtr;}; TreeNode *search(datatype x); bool insert(datatype x); TreeNode * remove(datatype x); TreeNode *getRoot(){return rootPtr;}; Tree *getLeftSubtree(); Tree *getRightSubtree(); bool isEmpty(){return rootPtr == NULL;}; private: TreeNode *rootPtr;};
22
Binary Search Trees
• A binary search tree (BST) is a binary tree where– Every node holds a data value (called key)– For any node x, all the keys in the left subtree
of x are ≤ the key of x– For any node x, all the keys in the right subtree
of x are > the key of x
23
Example of a BST
6
15
8
2
3 7
11
10
14
12
20
27
22 30
24
Searching in a BST
To search for a number b:
1. Compare b with the root;– If b=root, return
– If b<root, go left
– If b>root, go right
2. Repeat step 1, comparing b with the new node we are at.
3. Repeat until either the node is found or we reach a non-existing node
Try it with b=12, and also with b=17
6
158
2
3 7
11
10
14
12
20
27
22 30
25
Code for Search in BST
// returns a pointer to the TreeNode that contains x,// if one is found. Otherwise, it returns NULLTreeNode * Tree::search(datatype x){ if (isEmpty()) {return NULL;} TreeNode *p=rootPtr; while (p != NULL){ datatype a = p->getData(); if (a == x) return p; else if (x<a) p=p->getLeft(); else p=p->getRight(); } return NULL;};
26
Insertion into a BST
Insert(datatype b, Tree T):
1. Search for the position of b as if it were in the tree. The position is the left or right child of some node x.
2. Create a new node, and assign its address to the appropriate pointer field in x
3. Assign b to the data field of the new node
27
Illustration of Insert
6
158
2
3 7
11
10
14
12
20
27
22 30
Before inserting 25
6
158
2
3 7
11
10
14
12
20
27
22 30
25
After inserting 25
28
Code for Insert in BST
bool Tree::insert(datatype x){ if (isEmpty()) {rootPtr = new TreeNode(x);return true; } TreeNode *p=rootPtr; while (p != NULL){ datatype a = p->getData(); if (a == x) return false; // data is already there else if (x<a){ if (p->getLeft() == NULL){ // place to insert TreeNode *newNodePtr= new TreeNode(x); p->setLeft(newNodePtr); return true;} else p=p->getLeft(); }else { // a>a if (p->getRight() == NULL){ // place to insert TreeNode *newNodePtr= new TreeNode(x); p->setRight(newNodePtr); return true;} else p=p->getRight();} } };
29
Deletion from a BST (pseudocode)
Delete (datatype b, Tree T)1. Search for b in tree T. If not found, return.2. Call x the first node found to contain b3. If x is a leaf, remove x and set the
appropriate pointer in the parent of x to NULL
4. If x has only one child y, remove x, and the parent of x become a direct parent of y
(More on the next slide)
30
Deletion (contd.)
5. If x has two children, go to the left subtree, and find there in largest node, and call it y. The node y can be found by tracing the rightmost path until the end. Note that y is either a leaf or has no right child
6. Copy the data field of y onto the data field of x
7. Now delete node y in a manner similar to step 4.
31
Tree Traversal Techniques; Heaps
• Tree Traversal Concept• Tree Traversal Techniques: Preorder,
In-order, Post-order• Full Trees • Almost Complete Trees• Heaps
32
Binary-Tree Related Definitions
• The children of any node in a binary tree are ordered into a left child and a right child
• A node can have a left anda right child, a left childonly, a right child only,or no children
• The tree made up of a leftchild (of a node x) and all itsdescendents is called the left subtree of x
• Right subtrees are defined similarly
10
1
3
11
98
4 6
5
7
12
33
A Binary-tree Node Classclass TreeNode { public: typedef int datatype; TreeNode(datatype x=0, TreeNode *left=NULL,
TreeNode *right=NULL){data=x; this->left=left; this->right=right; };
datatype getData( ) {return data;};
TreeNode *getLeft( ) {return left;};
TreeNode *getRight( ) {return right;};void setData(datatype x) {data=x;};void setLeft(TreeNode *ptr) {left=ptr;};void setRight(TreeNode *ptr) {right=ptr;};
private:datatype data; // different data type for other appsTreeNode *left; // the pointer to left childTreeNode *right; // the pointer to right child
};
34
Binary Tree Class
class Tree { public: typedef int datatype; Tree(TreeNode *rootPtr=NULL){this->rootPtr=rootPtr;}; TreeNode *search(datatype x); bool insert(datatype x); TreeNode * remove(datatype x); TreeNode *getRoot(){return rootPtr;}; Tree *getLeftSubtree(); Tree *getRightSubtree(); bool isEmpty(){return rootPtr == NULL;}; private: TreeNode *rootPtr;};
35
Binary Tree Traversal
• Traversal is the process of visiting every node once
• Visiting a node entails doing some processing at that node, but when describing a traversal strategy, we need not concern ourselves with what that processing is
36
Binary Tree Traversal Techniques
• Three recursive techniques for binary tree traversal
• In each technique, the left subtree is traversed recursively, the right subtree is traversed recursively, and the root is visited
• What distinguishes the techniques from one another is the order of those 3 tasks
37
Preoder, Inorder, Postorder
• In Preorder, the root
is visited before (pre)
the subtrees traversals• In Inorder, the root is
visited in-between left
and right subtree traversal• In Preorder, the root
is visited after (pre)
the subtrees traversals
Preorder Traversal:1. Visit the root2. Traverse left subtree3. Traverse right subtree
Inorder Traversal:1. Traverse left subtree2. Visit the root3. Traverse right subtree
Postorder Traversal:1. Traverse left subtree2. Traverse right subtree3. Visit the root
38
Illustrations for Traversals
• Assume: visiting a node is printing its label
• Preorder: 1 3 5 4 6 7 8 9 10 11 12
• Inorder:4 5 6 3 1 8 7 9 11 10 12
• Postorder:4 6 5 3 8 11 12 10 9 7 1
1
3
11
98
4 6
5
7
12
10
39
Illustrations for Traversals (Contd.)
• Assume: visiting a node is printing its data
• Preorder: 15 8 2 6 3 711 10 12 14 20 27 22 30
• Inorder: 2 3 6 7 8 10 1112 14 15 20 22 27 30
• Postorder: 3 7 6 2 10 1412 11 8 22 30 27 20 15
6
158
2
3 7
11
10
14
12
20
27
22 30
40
Code for the Traversal Techniques• The code for visit
is up to you to
provide, depending
on the application
• A typical example
for visit(…) is to
print out the data
part of its input
node
void inOrder(Tree *tree){ if (tree->isEmpty( )) return; inOrder(tree->getLeftSubtree( )); visit(tree->getRoot( )); inOrder(tree->getRightSubtree( ));}
void preOrder(Tree *tree){ if (tree->isEmpty( )) return; visit(tree->getRoot( )); preOrder(tree->getLeftSubtree()); preOrder(tree->getRightSubtree());}
void postOrder(Tree *tree){ if (tree->isEmpty( )) return; postOrder(tree->getLeftSubtree( )); postOrder(tree->getRightSubtree( )); visit(tree->getRoot( ));}
41
Application of Traversal Sorting a BST
• Observe the output of the in-order traversal of the BST example two slides earlier
• It is sorted
• This is no coincidence
• As a general rule, if you output the keys (data) of the nodes of a BST using inorder traversal, the data comes out sorted in increasing order
42
Other Kinds of Binary Trees(Full Binary Trees)
• Full Binary Tree: A full binary tree is a binary tree where all the leaves are on the same level and every non-leaf has two children
• The first four full binary trees are:
43
Examples of Non-Full Binary Trees
• These trees are NOT full binary trees: (do you know why?)
44
Canonical Labeling ofFull Binary Trees
• Label the nodes from 1 to n from the top to the bottom, left to right
1 1
2 3
12 3
4 5 6 71
2 3
4 5 6 7
8 9 10 111213 14 15
Relationships between labelsof children and parent:
2i 2i+1i
45
Other Kinds of Binary Trees(Almost Complete Binary trees)
• Almost Complete Binary Tree: An almost complete binary tree of n nodes, for any arbitrary nonnegative integer n, is the binary tree made up of the first n nodes of a canonically labeled full binary
1 1
21
2 3
4 5 6 7
1
2
1
2 3
4 5 6
1
2 3
4
1
2 3
4 5
46
Depth/Height of Full Trees and Almost Complete Trees
• The height (or depth ) h of such trees is O(log n)• Proof: In the case of full trees,
– The number of nodes n is: n=1+2+22+23+…+2h=2h+1-1
– Therefore, 2h+1 = n+1, and thus, h=log(n+1)-1
– Hence, h=O(log n)
• For almost complete trees, the proof is left as an exercise.
47
Canonical Labeling ofAlmost Complete Binary Trees
• Same labeling inherited from full binary trees
• Same relationship holding between the labels of children and parents:
Relationships between labelsof children and parent:
2i 2i+1i
48
Array Representation of Full Trees and Almost Complete Trees
• A canonically label-able tree, like full binary trees and almost complete binary trees, can be represented by an array A of the same length as the number of nodes
• A[k] is identified with node of label k• That is, A[k] holds the data of node k• Advantage:
– no need to store left and right pointers in the nodes save memory
– Direct access to nodes: to get to node k, access A[k]
49
Illustration of Array Representation
• Notice: Left child of A[5] (of data 11) is A[2*5]=A[10] (of data 18),
and its right child is A[2*5+1]=A[11] (of data 12). • Parent of A[4] is A[4/2]=A[2], and parent of A[5]=A[5/2]=A[2]
6
158
2 11
18 12
20
27
13
30
15 8 20 2 11 30 27 13 6 10 121 2 3 4 5 6 7 8 9 10 11
50
Adjustment of Indexes
• Notice that in the previous slides, the node labels start from 1, and so would the corresponding arrays
• But in C/C++, array indices start from 0• The best way to handle the mismatch is to adjust the
canonical labeling of full and almost complete trees.• Start the node labeling from 0 (rather than 1).• The children of node k are now nodes (2k+1) and
(2k+2), and the parent of node k is (k-1)/2, integer division.
51
Application of Almost Complete Binary Trees: Heaps
• A heap (or min-heap to be precise) is an almost complete binary tree where– Every node holds a data value (or key)– The key of every node is ≤ the keys of the
children
Note:A max-heap has the same definition except that the Key of every node is >= the keys of the children
52
Example of a Min-heap
16
5
8
15 11
18 12
20
27
33
30
53
Operations on Heaps
• Delete the minimum value and return it. This operation is called delete-Min.
• Insert a new data value
Applications of Heaps:• A heap implements a priority queue, which is a queue that orders entities not a on first-come first-serve basis, but on a priority basis: the item of highest priority is at the head, and the item of the lowest priority is at the tail
• Another application: sorting, which will be seen later
54
Delete-Min in Min-heaps
• The minimum value in a min-heap is at the root!• To delete the min, you can’t just remove the data
value of the root, because every node must hold a key
• Instead, take the last node from the heap, move its key to the root, and delete that last node
• But now, the tree is no longer a heap (still almost complete, but the root key value may no longer be ≤ the keys of its children
55
Illustration of First Stage of delete-min
16
5
8
15 11
18 12
20
27
33
30
16
8
15 11
18 12
20
27
33
30
16
8
15 11
18
1220
27
33
30
16
8
15 11
18
1220
27
33
30
56
Restore Heap
• To bring the structure back to its “heapness”, we restore the heap
• Swap the new root key with the smaller child.
• Now the potential bug is at the one level down. If it is not already ≤ the keys of its children, swap it with its smaller child
• Keep repeating the last step until the “bug” key becomes ≤ its children, or the it becomes a leaf
57
Illustration of Restore-Heap
16
8
15 11
18
1220
27
33
30
16
12
15 11
18
820
27
33
30
16
11
15 12
18
820
27
33
30
Now it is a correct heap
58
Time complexity of insertand delete-min
• Both operations takes time proportional to the height of the tree– When restoring the heap, the bug moves from level to
level until, in the worst case, it becomes a leaf (in delete-min) or the root (in insert)
– Each move to a new level takes constant time– Therefore, the time is proportional to the number of
levels, which is the height of the tree.
• But the height is O(log n)• Therefore, both insert and delete-min take O(log
n) time, which is very fast.
59
Inserting into a min-heap
• Suppose you want to insert a new value x into the heap
• Create a new node at the “end” of the heap (or put x at the end of the array)
• If x is >= its parent, done• Otherwise, we have to restore the heap:
– Repeatedly swap x with its parent until either x reaches the root of x becomes >= its parent
60
The Min-heap Class in C++
class Minheap{ //the heap is implemented with a dynamic array public: typedef int datatype; Minheap(int cap = 10){capacity=cap; length=0; ptr = new datatype[cap];}; datatype deleteMin( ); void insert(datatype x); bool isEmpty( ) {return length==0;}; int size( ) {return length;}; private: datatype *ptr; // points to the array int capacity; int length; void doubleCapacity(); //doubles the capacity when needed};
61
Code for delete-min
Minheap::datatype Minheap::deleteMin( ){ assert(length>0); datatype returnValue = ptr[0]; length--; ptr[0]=ptr[length]; // move last value to root element int i=0; while ((2*i+1<length && ptr[i]>ptr[2*i+1]) || (2*i+2<length && (ptr[i]>ptr[2*i+1] || ptr[i]>ptr[2*i+2]))){ // “bug” still > at least one child if (ptr[2*i+1] <= ptr[2*i+2]){ // left child is the smaller child datatype tmp= ptr[i]; ptr[i]=ptr[2*i+1]; ptr[2*i+1]=tmp; //swap i=2*i+1; } else{ // right child if the smaller child. Swap bug with right child. datatype tmp= ptr[i]; ptr[i]=ptr[2*i+2]; ptr[2*i+2]=tmp; // swap i=2*i+2; } } return returnValue; };
62
Code for Insert
void Minheap::insert(datatype x){ if (length==capacity) doubleCapacity(); ptr[length]=x; int i=length; length++; while (i>0 && ptr[i] < ptr[i/2]){ datatype tmp= ptr[i]; ptr[i]=ptr[(i-1)/2]; ptr[(i-1)/2]=tmp; i=(i-1)/2; }};
63
Code for doubleCapacity
void Minheap::doubleCapacity(){ capacity = 2*capacity; datatype *newptr = new datatype[capacity]; for (int i=0;i<length;i++) newptr[i]=ptr[i]; delete [] ptr; ptr = newptr;};
64
End of Lecture