Grundläggande datalogi - Övning 3 Björn Terelius November 14, 2008
Utskrift av stackar Tornen i Hanoi Principerna för rekursion: Hitta ett enkelt basfall (som har en känd lösning). Reducera varje annat problem till en mindre instans av samma problem. Observera att delproblemen måste närma sig basfallet för att undvika en oändlig rekursion.
Utskrift av stackar Tornen i Hanoi def print_stack_top_down(s): "Print a stack with the top element first" if not s.empty(): top = s.pop() print top print_stack_top_down(s) s.push(top) def print_stack_bottom_up(s): "Print a stack with the bottom element first" if not s.empty(): top = s.pop() print_stack_bottom_up(s) print top s.push(top)
Utskrift av stackar Tornen i Hanoi Problem: Flytta n skivor från den första pinnen till den tredje pinnen på ett sådant sätt att en större skiva aldrig ligger på en mindre. def movetower(n, fromp, top, withp): if n>0: moves = movetower(n-1, fromp, withp,top) moves += 1 print "Move disk from", fromp, "to", top moves += movetower(n-1, withp, top, fromp) return moves return 0
class Node... def preorder(self, l): l.append(self.item) if self.left!=none: self.left.preorder(l) if self.right!=none: self.right.preorder(l) def inorder(self, l): if self.left!=none: self.left.inorder(l) l.append(self.item) if self.right!=none: self.right.inorder(l)
class BinarySearchTree: def preorder(self): """Return a list of the nodes in preorder, i.e. if inserted they rebuild the tree""" l = [] if self.root!= None: self.root.preorder(l) return l def inorder(self): """Return a list of all nodes in inorder, i.e. the elements are sorted""" l = [] if self.root!= None: self.root.inorder(l) return l
Giriga algoritmer Divide and conquer Dynamisk programmering Tre specialfall: Giriga algoritmer - Välj det lokalt bästa i varje steg. Giriga algoritmer går ofta att skriva utan rekursion. Divide and conquer - Dela problemet i flera delproblem och lös varje delproblem för sig. Lös det ursprungliga problemet genom att kombinera lösningarna till delproblemen. Dynamisk programmering - Spara och återanvänd delresultat om samma delproblem uppstår flera gånger.
Giriga algoritmer Divide and conquer Dynamisk programmering class Sack: def init (self, name, value, weight): self.name = name self.value = float(value) self.weight = float(weight) def value_per_weight(sack1, sack2): if s1.value/s1.weight > s2.value/s2.weight: return -1 if s1.value/s1.weight < s2.value/s2.weight: return 1 return 0
Giriga algoritmer Divide and conquer Dynamisk programmering def fractional_knapsack(sacks, limit): """ Given a list of the total value and weight of each sack, find the maximal value we can get. """ sacks.sort(value_per_weight) total_value = 0 for s in sacks: if s.weight<=limit: print "Take", s.weight, "kg of", s.name total_value+=s.value limit=limit-s.weight else: print "Take", limit, "kg of", s.name total_value+=(s.value/s.weight)*limit limit = 0 break return total_value
Giriga algoritmer Divide and conquer Dynamisk programmering 1. Dela upp listan i två halvor 2. Sortera varje halva rekursivt 3. Sätt ihop de sorterade halvorna till en helt sorterad lista def merge_sort(l): """ Return a sorted copy of l """ if len(l)<=1: return l n=len(l) l1 = merge_sort(l[n//2:]) l2 = merge_sort(l[:n//2]) return merge(l1, l2)
Giriga algoritmer Divide and conquer Dynamisk programmering def merge(l1, l2): i=j=0 sorted = [] while i<len(l1) or j<len(l2): if i==len(l1): sorted.append(l2[j]) j = j+1 elif j==len(l2): sorted.append(l1[i]) i = i+1 elif l1[i]<l2[j]: sorted.append(l1[i]) i = i+1 else: sorted.append(l2[j]) j = j+1 return sorted
Giriga algoritmer Divide and conquer Dynamisk programmering def bin(n,k): "Computes the binomial coefficient n-choose-k" if k==0 or k==n: return 1 else: return bin(n-1, k) + bin(n-1, k-1) # Create a 2D square table with all elements 0 def bin(n,k): "Computes the binomial coefficient n-choose-k" if table[n][k]==0: if k==0 or k==n: table[n][k] = 1 else: table[n][k] = bin(n-1, k)+bin(n-1, k-1) return table[n][k]