algorithms in systems engineering ise 172 lecture...
TRANSCRIPT
-
Algorithms in Systems EngineeringISE 172
Lecture 13
Dr. Ted Ralphs
-
ISE 172 Lecture 13 1
References for Today’s Lecture
• Required reading
– Sections 6.1-6.36
• References
– CLRS Chapter 21 and 22– R. Sedgewick, Algorithms in C++ (Third Edition), 1998.
1
-
ISE 172 Lecture 13 2
Trees
• A tree is a set of items organized into a hierarchical structure (think ofa family tree).
• When organized in this way, we call the items nodes.
• Each node has a single designated parent and one or more children.
• There is a single designated node, called the root, with no parent.
• Any node with no children is called a leaf.
• Any node with children is called internal.
• A tree in which all nodes have 2 or fewer children is called a binary tree.
• Storing a list of items in a tree structure allows us to represent additionalrelationships among the items in the list.
• Trees occur naturally in a wide variety of applications.
2
-
ISE 172 Lecture 13 3
Trees in Action
• File system
• Philogenic Trees
• Family Trees
• Call Trees
• Web page
3
-
ISE 172 Lecture 13 4
A Family Tree (Mathematics Geneology
Rolf Hermann MöhringRheinisch-Westfälische Technische Hochschule Aachen 1975
Anselm SchulzeRWTH Aachen 1986
Dorothea WagnerRWTH Aachen 1986
Norbert KorteRWTH Aachen 1987
Stefan FelsnerTU Berlin 1992
Jens GustedtTU Berlin 1992
Rudolf MüllerTU Berlin 1993
Andreas Parra AsensioTU Berlin 1996
Markus SchäffterTU Berlin 1996
Andreas S. SchulzTU Berlin 1996
Ewa MalesinskaTU Berlin 1997
Matthias Müller-HannemannTU Berlin 1997
Martin SkutellaTU Berlin 1998
Stephan HartmannTU Berlin 1999
Ekkehard KöhlerTU Berlin 1999
Michael NaatzTU Berlin 2001
Frederik StorkTU Berlin 2001
Marc UetzTU Berlin 2001
Georg BaierTU Berlin 2003
Vanessa KääbTU Berlin 2003
Katharina LangkauTU Berlin 2003
Christian LiebchenTU Berlin 2006
Heiko SchillingTU Berlin 2006
Nicole MegowTU Berlin 2006
Ines SpenkeTU Berlin 2006
Walter OberschelpWestfälische Wilhelms-Universität Münster 1958
Rolf KaerkesRheinisch-Westfälische Technische Hochschule Aachen 1963
Hans HermesWestfälische Wilhelms-Universität Münster 1938
Hubert CremerUniversität Berlin 1927
Heinz KönigChristian-Albrechts-Universität zu Kiel 1952
Heinrich ScholzFriedrich-Alexander-Universität Erlangen-Nürnberg 1913
Ludwig BieberbachGeorg-August-Universität Göttingen 1910
Karl-Heinrich WeiseFriedrich-Schiller-Universität Jena 1934
Richard FalckenbergFriedrich-Schiller-Universität Jena 1877
C. Felix (Christian) KleinRheinische Friedrich-Wilhelms-Universität Bonn 1868
C. L. Ferdinand (Carl Louis) LindemannFriedrich-Alexander-Universität Erlangen-Nürnberg 1873
Robert Johann Maria KönigGeorg-August-Universität Göttingen 1907
Kuno Ernst Berthold FischerMartin-Luther-Universität Halle-Wittenberg 1847
Julius PlückerPhilipps-Universität Marburg 1823
Rudolf Otto Sigismund LipschitzUniversität Berlin 1853
David HilbertUniversität Königsberg 1885
Johann Eduard ErdmannChristian-Albrechts-Universität zu Kiel 1830
Christian Ludwig GerlingGeorg-August-Universität Göttingen 1812
Gustav Peter Lejeune DirichletRheinische Friedrich-Wilhelms-Universität Bonn 1827
Martin OhmFriedrich-Alexander-Universität Erlangen-Nürnberg 1811
Georg Wilhelm Friedrich HegelFriedrich-Schiller-Universität Jena 1801
Carl Friedrich GaußUniversität Helmstedt 1799
Simeon Denis PoissonÉcole Polytechnique
Jean-Baptiste Joseph Fourier
Karl Christian von LangsdorfUniversität Erfurt 1781
Friedrich Wilhem Joseph von SchellingEberhard-Karls-Universität Tübingen 1795
Johann Friedrich PfaffGeorg-August-Universität Göttingen 1786
Joseph Louis Lagrange
Johann Gottlieb FichteUniversität Königsberg 1792
Abraham Gotthelf KästnerUniversität Leipzig 1739
Leonhard EulerUniversität Basel 1726
Immanuel KantUniversität Königsberg 1770
Christian August HausenMartin-Luther-Universität Halle-Wittenberg 1713
Johann BernoulliUniversität Basel 1694
Martin Knutzen
Marcus Herz
Johann Christoph WichmannshausenUniversität Leipzig 1685
Jacob BernoulliUniversität Basel 1684
Christian M. von WolffUniversität Leipzig 1704
Otto MenckeUniversität Leipzig 1665, 1666
Gottfried Wilhelm LeibnizUniversität Altdorf 1666
Ehrenfried Walter von Tschirnhaus
Erhard WeigelUniversität Leipzig 1650
4
-
ISE 172 Lecture 13 5
An Tree Generated in Python
5
-
ISE 172 Lecture 13 6
Trees and Recursion
def draw_r(self, branchLen):
if branchLen > 5:
self.turtle.forward(branchLen)
self.turtle.right(20)
self.draw_r(branchLen-15)
self.turtle.left(40)
self.draw_r(branchLen-10)
self.turtle.right(20)
self.turtle.backward(branchLen)
6
-
ISE 172 Lecture 13 7
Non-recursive Version
def draw_nr_static1(self, branchLen):
s = Stack()
while True:
if branchLen > 5:
self.turtle.forward(branchLen)
self.turtle.left(20)
s.push((branchLen-10,
self.turtle.position(),
self.turtle.heading()))
self.turtle.right(40)
s.push((branchLen-15,
self.turtle.position(),
self.turtle.heading()))
self.turtle.left(20)
if s.isEmpty():
break
branchLen, p, h = s.pop()
self.turtle.setheading(h); self.turtle.penup()
self.turtle.goto(p); self.turtle.pendown()
7
-
ISE 172 Lecture 13 8
A Tree Representing Location of Ruler Hashmarks
8
-
ISE 172 Lecture 13 9
The Code
def ruler(hash_marks, left = 0, right = 16, height = 3):
if height > 0:
middle = (left+right)//2
ruler(hash_marks, left, middle, height - 1)
hash_marks[middle] = height
ruler(hash_marks, middle, right, height - 1)
def ruler_nr(hash_marks, left = 0, right = 16, height = 3):
for i in range(height):
for j in range(left+right//(2**(height-i)), right,
right//(2**(height-i))):
hash_marks[j] = i+1
9
-
ISE 172 Lecture 13 10
Additional Terminology
• The level of a node in the tree is the number of recursive calls toparent() needed to reach the root.
• The depth of the tree is the maximum level of any of its nodes.
• A balanced tree is one in which all leaves are at levels k or k − 1, wherek is the depth of the tree.
• Additional terms
– Edge– Path– Siblings– Subtree
10
-
ISE 172 Lecture 13 11
Tree Data Structures
• The tree ADT can be thought of as a list ADT with additional structure.
• One of the most important roles of the additional structure is to allowfor the list to be traversed easily in various orders.
• We may also want to be able to be able to query the relationships of agiven node to others (parent/sibling/child).
11
-
ISE 172 Lecture 13 12
Tree ADT
class Tree:
def __init__(self, root)
def add_root(self, n, **attrs)
def get_root(self)
def add_child(self, name, parent, **attrs)
def get_children(self, name) # return list of children
def get_parent(self, name)
def print_nodes(self, order, priority) # binary tree only
def traverse(self, q) # print nodes in order
def __contains__(self, name)
def __iter__(self) # iterate over nodes in order
12
-
ISE 172 Lecture 13 13
Additional Functionality
• Later, we’ll want to be able to “splice” nodes into the tree at particularplaces.
• We’ll also want to be able to do certain “rotations” in which we changethe parent/child relationships in a systematic way.
• The goal of these operations will be to maintain a certain structure inthe tree.
• This will make certain kinds of additions, deletions, and traversals efficientso we can implement additional operations.
13
-
ISE 172 Lecture 13 14
Traversing a Tree
• Traversing a tree consists of visiting the nodes in a specified order,starting at the root node.
• As we encounter each node, we put all of its children on the list to bevisited.
• The order in which we take nodes off this list determined the searchorder.
– Depth-first: Last in, first out. This means that we visit the node inthe list at the deepest level first.
– Breadth-first: First in, first out. This means we visit the node in thelist at the shallowest level first.
14
-
ISE 172 Lecture 13 15
Traversing a Tree (Depth First)
Here is a recursive implementation of a depth-first search.
def dfs(self, root):
print root
for i in self.get_children(current):
print i
self.depth(root)
15
-
ISE 172 Lecture 13 16
Traversing a Tree (Depth First)
We can also do depth-first search with a stack
def dfs(self):
s = Stack()
s.push(self.get_root)
while s.isEmpty() != True:
current = s.pop()
print current
for i in self.get_children(current):
s.push(i)
16
-
ISE 172 Lecture 13 17
Traversing a Tree (Breadth First)
To get breadth first search, we can simply replace the stack with a queue:
def dfs(self):
s = Queue()
s.enqueue(self.get_root)
while s.isEmpty() != True:
current = s.dequeue()
print current
for i in self.get_children(current):
s.enqueue(i)
17
-
ISE 172 Lecture 13 18
Breadth First Search of Generated Tree
def draw nr static1(self, branchLen):
s = Queue()
while True:
if branchLen > 5:
self.turtle.forward(branchLen)
self.turtle.left(20)
s.push((branchLen-10,
self.turtle.position(),
self.turtle.heading()))
self.turtle.right(40)
s.push((branchLen-15,
self.turtle.position(),
self.turtle.heading()))
self.turtle.left(20)
if s.isEmpty():
break
branchLen, p, h = s.pop()
self.turtle.setheading(h); self.turtle.penup()
self.turtle.goto(p); self.turtle.pendown()
18
-
ISE 172 Lecture 13 19
Binary Trees
• In many applications, the trees that arise are binary by nature.
• The call tree in quicksort or mergesort is an example.
• When we know that there will be at most two children of a given node,we call them the right and left children.
• We can specialize the ADT by adding methods to access the right andleft children directly.
– get parent(name): return the parent of node index.– get right child(name): return the “right” child of node name.– get left child(name): return the “left” child of node name.
19
-
ISE 172 Lecture 13 20
Binary Tree ADT
class BinaryTree(Tree):
def get_left_child(self, name):
get_children(index)[0]
def get_right_child(self, name):
get_children(index)[1]
20
-
ISE 172 Lecture 13 21
Traversing a Binary Tree (Pre-order)
When doing a depth first search, if we print each node before searchingeither of the children recursively, this produces an “pre-order” traversal.
def depth(self, root):
print root
self.depth(get_left(root))
self.depth(get_right(root))
21
-
ISE 172 Lecture 13 22
Traversing a Binary Tree (In-order)
Alternatively, if we print each node in between searching the left and rightsubtrees, this produces an “in-order” traversal.
def depth(self, root):
self.depth(get_left(root))
print root
self.depth(get_right(root))
22
-
ISE 172 Lecture 13 23
Traversing a Binary Tree (Post-order)
Finally, if we print each node after searching both the left and right subtrees,this produces an “in-order” traversal.
def depth(self, root):
self.depth(get_left(root))
self.depth(get_right(root))
print root
23
-
ISE 172 Lecture 13 24
Running Time of Tree Traversal
• What is the running time of these tree traversal methods?
24
-
ISE 172 Lecture 13 25
Example: Expression Tree
25