Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1747321
  • 博文数量: 297
  • 博客积分: 285
  • 博客等级: 二等列兵
  • 技术积分: 3006
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-06 22:04
个人简介

Linuxer, ex IBMer. GNU https://hmchzb19.github.io/

文章分类

全部博文(297)

文章存档

2020年(11)

2019年(15)

2018年(43)

2017年(79)

2016年(79)

2015年(58)

2014年(1)

2013年(8)

2012年(3)

分类: Python/Ruby

2015-09-16 10:27:06

重看Data structure and algorithms in python,仍然感觉数据结构真心难。
从tree->binary tree-> linked binary tree->euler tour,看的想吐

点击(此处)折叠或打开

  1. """
  2. p.element( ): Return the element stored at position p.
  3. The tree ADT then supports the following accessor methods, allowing a user to
  4. navigate the various positions of a tree:
  5. T.root( ): Return the position of the root of tree T,
  6. or None if T is empty.
  7. T.is root(p): Return True if position p is the root of Tree T.
  8. T.parent(p): Return the position of the parent of position p,
  9. or None if p is the root of T.
  10. T.num children(p): Return the number of children of position p.
  11. T.children(p): Generate an iteration of the children of position p.
  12. T.is leaf(p): Return True if position p does not have any children.
  13. len(T): Return the number of positions (and hence elements) that
  14. are contained in tree T.
  15. T.is empty( ): Return True if tree T does not contain any positions.
  16. T.positions( ): Generate an iteration of all positions of tree T.
  17. iter(T): Generate an iteration of all elements stored within tree T.
  18. """

  19. class Tree:
  20.     #Abstract base class representing a tree structure

  21.     class Position:
  22.         #return the element stored at this position
  23.         def element(self):
  24.             raise NotImplementedError('must be implemented by subclass')

  25.         def __eq__(self,other):
  26.             #return true if other position represents the same location
  27.             raise NotImplementedError('must be implemented by subclass')

  28.         def __net__(self,other):
  29.             return not(self ==other)

  30.     #abstract methods that concrete subclass must support
  31.     def root(self):
  32.         #return position representing the tree's root(or None if empty)
  33.         raise NotImplementedError('must be implemented by subclass')

  34.     def parent(self,p):
  35.         #Return the number of children that Position p has.
  36.         raise NotImplementedError('must be implemented by subclass')

  37.     def num_children(self,p):
  38.         #return the number of children that position p has
  39.         raise NotImplementedError('must be implemented by subclass')

  40.     def children(self,p):
  41.         #Generate an iteration of Positions representing p's children
  42.         raise NotImplementedError('must be implemented by subclass')

  43.     def __len__(self):
  44.         #return the total number of elements in the tree
  45.         raise NotImplementedError('must be implemented by subclass')

  46.     #concrete method implemented in this class
  47.     def is_root(self,p):
  48.         #return True if position p represents the root of the tree
  49.         return self.root()==p

  50.     def is_leaf(self,p):
  51.         return self.num_children(p)==0

  52.     def is_empty(self):
  53.         #return true if three is empty
  54.         return len(self)==0

  55.     def depth(self,p):
  56.         #return the number of levels separating Position p from the root
  57.         if self.is_root(p):
  58.             return 0
  59.         else:
  60.             return 1+self.depth(self.parent(p))

  61.     def _height1(self,p): #works ,but n**2 worst-case time
  62.         #return the height of the tree
  63.         return max(self.depth(p) for p in self.positions() is self.is_leaf(p))

  64.     def _height2(self,p):
  65.         #return the height of the subtree rooted at position p
  66.         if self.is_leaf(p):
  67.             return 0
  68.         else:
  69.             return 1+max(self._height2(c) for c in self.children(p))

  70.     def height(self,p=None):
  71.         #return the height of the subtree rooted at Position p
  72.         #if p is None,return the height of the entire tree
  73.         if p is None:
  74.             p=self.root()
  75.         return self._height2(p)
  76.     
  77.     def __iter__(self):
  78.         #generate an interation of the tree's elements
  79.         for p in self.positions(): #use same order as positions()
  80.             yield p.element() #but yield each element

  81.     def preorder(self):
  82.         #generate a preorder iterationm of positions in the tree
  83.         if not self.is_empty():
  84.             for p in self._subtree_preorder(self.root()): #start recursion
  85.                 yield p

  86.     def _subtree_preorder(self,p):
  87.         #generate a preorder iteration of position in subtree rooted at p
  88.         yield p #visit p before its subtrees
  89.         for c in self.children(p): #for each child c
  90.             for other in self._subtree_preorder(c): #do preorder of c's subtree
  91.                 yield other #yielding each to our caller

  92.     def positions(self):
  93.         #generate an iteration of the tree's positions
  94.         return self.preorder() #return entire preorder iteration

  95.     def postorder(self):
  96.         #generate a postorder iteration of positions in the tree
  97.         if not self.is_empty():
  98.             for p in self._subtree_postorder(self.root()): #start recursion
  99.                 yield p

  100.     def _subtree_postorder(self,p):
  101.         #generate a postorder iteration of positions in subtree rooted at p
  102.         for c in self.children(p): #for each child c
  103.             for other in self._subtree_postorder(c): #do postorder of c's subtree
  104.                 yield other #yield each to our caller
  105.             yield p #visit p after its subtrees
  106.     
  107.     def breadfirst(self):
  108.         #generate a breadth-first iteration of the positions of the tree
  109.         if not self.is_empty():
  110.             fringe=LinkedQueue() #known positions not yet yielded
  111.             fringe.enqueue(self.root()) #starting with the root
  112.             while not fringe.is_empty():
  113.                 p=fringe.dequeue() #remove from front of the queue
  114.                 yield p
  115.                 for c in self.children(p):
  116.                     fringe.enqueue(c) #add children to back of queue

  117. """Binary Tree
  118. T.left(p): Return the position that represents the left child of p,
  119. or None if p has no left child.
  120. T.right(p): Return the position that represents the right child of p,
  121. or None if p has no right child.
  122. T.sibling(p): Return the position that represents the sibling of p,
  123. or None if p has no sibling.
  124. """

  125. class BinaryTree(Tree):
  126.     #Abstract base class representing a binary tree
  127.     def left(self,p):
  128.         #return a Position representing p's left child
  129.         #return None if p does not have
  130.         raise NotImplementedError('must be implemented by subclass')

  131.     def right(self,p):
  132.         #return a Position representing p's right child
  133.         #return None if p does not have
  134.         raise NotImplementedError('must be implemented by subclass')

  135.     #concrete methods implemented
  136.     def sibling(self,p):
  137.         #return a Position representing p's sibling
  138.         #or None if no sibling
  139.         parent=self.parent(p)
  140.         if parent is None: #p must be root
  141.             return None #root has no sibling
  142.         else:
  143.             if p==self.left(parent):
  144.                 return self.right(parent) #possibly None
  145.             else:
  146.                 return self.left(parent) #possibly None

  147.     def children(self,p):
  148.         #Generate an iteration of Position representing p's children
  149.         if self.left(p) is not None:
  150.             yield self.left(p)
  151.         if self.right(p) is not None:
  152.             yield self.right(p)

  153.     def inorder(self):
  154.         #generate an inorder iteration of positions in the tree
  155.         if not self.is_empty():
  156.             for p in self._subtree_inorder(self.root()):
  157.                 yield p

  158.     def _subtree_inorder(self,p):
  159.         #generate an inorder iteration of positions in subtree rooted at p
  160.         if self.left(p) is not None: #if left child exists, traverse its subtree
  161.             for other in self._subtree_inorder(self.left(p)):
  162.                 yield other
  163.         yield p #visit p between its subtree
  164.         if self.right(p) is not None: #if right child exists,traverse its subtree
  165.             for other in self._subtree_inorder(self.right(p)):
  166.                 yield other
  167.     
  168.     #override inherited version to make inorder the default
  169.     def positions(self):
  170.         #generate an iteration of the tree's positions
  171.         return self.inorder() #make inorder the default


  172.             

  173. """
  174. T.add root(e): Create a root for an empty tree, storing e as the element,
  175. and return the position of that root; an error occurs if the
  176. tree is not empty.
  177. T.add left(p, e): Create a new node storing element e, link the node as the
  178. left child of position p, and return the resulting position;
  179. an error occurs if p already has a left child.
  180. T.add right(p, e): Create a new node storing element e, link the node as the
  181. right child of position p, and return the resulting position;
  182. an error occurs if p already has a right child.
  183. T.replace(p, e): Replace the element stored at position p with element e,
  184. and return the previously stored element.
  185. T.delete(p): Remove the node at position p, replacing it with its child,
  186. if any, and return the element that had been stored at p;
  187. an error occurs if p has two children.
  188. T.attach(p, T1, T2): Attach the internal structure of trees T1 and T2, respec-
  189. tively, as the left and right subtrees of leaf position p of
  190. T, and reset T1 and T2 to empty trees; an error condition
  191. occurs if p is not a leaf.
  192. """

  193. class LinkedBinaryTree(BinaryTree):
  194.     #LInked representation of a binary tree structure

  195.     class _Node:
  196.         __slots__='_element','_parent','_left','_right'

  197.         def __init__(self,element,parent=None,left=None,right=None):
  198.             self._element=element
  199.             self._parent=parent
  200.             self._left=left
  201.             self._right=right

  202.     class Position(BinaryTree.Position):
  203.         #An abstraction representing the location of single element
  204.         def __init__(self,container,node):
  205.             #constructor should not be invoked by user
  206.             self._container=container
  207.             self._node=node

  208.         def element(self):
  209.             #return the element stored at this position
  210.             return self._node._element

  211.         def __eq__(self,other):
  212.             #return true if other is position representing the same location
  213.             return type(other) is type(self) and other._node is self._node

  214.     def _validate(self,p):
  215.         #return associated node,if position is valid
  216.         if not isinstance(p,self.Position):
  217.             raise TypeError('p must be proper Position type')
  218.         if p._container is not self:
  219.             raise ValueError('p does not belong to this container')
  220.         if p._node._parent is p._node: #convention for deprecated nodes
  221.             raise ValueError('p is no longer valid')
  222.         return p._node

  223.     def _make_position(self,node):
  224.         #return Position instance for given node(or None if no node)
  225.         return self.Position(self,node) if node is not None else None


  226.     def __init__(self):
  227.         #create an initially empty binary tree
  228.         self._root=None
  229.         self._size=0

  230.     #public accessors
  231.     def __len__(self):
  232.         return self._size

  233.     def root(self):
  234.         #return the root position of the ree(or None if tree is mepty)
  235.         return self._make_position(self._root)

  236.     def parent(self,p):
  237.         #return the position of p's parent (or None if p is root)
  238.         node=self._validate(p)
  239.         return self._make_position(node._parent)

  240.     def left(self,p):
  241.         #return the position of p's left child(or NOne if no left child)
  242.         node=self._validate(p)
  243.         return self._make_position(node._left)

  244.     def right(self,p):
  245.         #return the position p's right child (or None if no right child)
  246.         node=self._validate(p)
  247.         return self._make_position(node._right)

  248.     def num_children(self,p):
  249.         #return the number of children of position p
  250.         node=self._validate(p)
  251.         count=0
  252.         if node._left is not None:
  253.             count+=1
  254.         if node._right is not None:
  255.             count+=1
  256.         return count

  257.     def _add_root(self,e):
  258.         #place element e at the root of an empty tree and return new position
  259.         #Raise ValueError if tree nonempty
  260.         if self._root is not None: raise ValueError('Root exists')
  261.         self._size=1
  262.         self._root=self._Node(e)
  263.         return self._make_position(self._root)

  264.     def _add_left(self,p,e):
  265.         #create a new left child for Position p,storing element e
  266.         #return the position of new node
  267.         #Raise ValueError if Position p is invalid or p already has a left child
  268.         node=self._validate(p)
  269.         if node._left is not None: raise ValueError('left child exists')
  270.         self._size+=1
  271.         node._left=self._Node(e,node)
  272.         return self._make_position(node._left)

  273.     def _add_right(self,p,e):
  274.         #create a new right child for position,p storing element e
  275.         #return the position of new node
  276.         #Raise ValueError if position P is invalide or p already has a right child
  277.         node=self._validate(p)
  278.         if node._right is not None: raise ValueError('Right child exists')
  279.         self._size+=1
  280.         node._right=self._Node(e,node)
  281.         return self._make_position(node._right)

  282.     def _replace(self,p,e):
  283.         #replace the element at position p with e,and return old element
  284.         node=self._validate(p)
  285.         old=node._element
  286.         node._element=e
  287.         return old

  288.     def _delete(self,p):
  289.         #Delete the node at position p,and replace it with it's child
  290.         #return the element stored at position p
  291.         #raise ValueError if position p is invalid or p has two children
  292.         node=self._validate(p)
  293.         if self.num_child(p)==2: raise ValueError('p has two children')
  294.         child=node._left if node._left else node._right #might be none
  295.         if child is not None:
  296.             child._parent=node._parent
  297.         if node is self._root:
  298.             self._root=child
  299.         else:
  300.             parent=node._parent
  301.             if node is parent._left:
  302.                 parent._left=child
  303.             else:
  304.                 parent._right=child
  305.         self._size-=1
  306.         node._parent=node
  307.         return node._element

  308.     def _attach(self,p,t1,t2):
  309.         #attach tree t1 and t2 as left and right subtress of external p
  310.         node=self._validate(p)
  311.         if not self.is_leaf(p): raise ValueError('Position must be leaf')
  312.         if not type(self) is type(t1) is type(t2): #all 3 trees must be same type
  313.             raise TypeError('Tree types must match')
  314.         self._size+=len(t1)+len(t2)
  315.         if not t1.is_empty(): #attached t1 as left subtree
  316.             t1._root._parent=node
  317.             node._left=t1._root
  318.             t1._root=None #set t1 instance to empty
  319.             t1._size=0
  320.         if not t2.is_empty():
  321.             t2._root._parent=node
  322.             node._right=t2._root
  323.             t2._root=None #set t2 instance to empty
  324.             t2._size=0


  325. class EulerTour:
  326.     #abstract base class for performing Euler tour of a tree
  327.     #_hook_previsit and _hook_postvisit may be overridden by subclasses

  328.     def __init__(self,tree):
  329.         #prepare an Euler tour template for given tree
  330.         self._tree=tree

  331.     def tree(self):
  332.         #return reference to the tree being traversed
  333.         return self._tree

  334.     def execute(self):
  335.         #perform the tour and return any result from post viist of root
  336.         if len(self._tree)>0:
  337.             return self._tour(self._tree.root(),0,[]) #start the recursion

  338.     def _tour(self,p,d,path):
  339.         #perform tour of subtree rooted at Position p
  340.         #p Position of current node being visited
  341.         #d depth of p in the tree
  342.         #path list of indices of children on path from root to p
  343.         self._hook_previsit(p,d,path) #"pre visit" p
  344.         results=[]
  345.         path.append(0) #add new index to end of path before recursion
  346.         for c in self._tree.children(p):
  347.             results.append(self._tour(c,d+1,path)) #result on child's subtree
  348.             path[-1]+=1 #increment index
  349.         path.pop() #remove extraneous index
  350.         answer=self._hook_postvisit(p,d,path,results)
  351.         return answer

  352.     def _hook_previsit(self,p,d,path):
  353.         pass

  354.     def _hook_postvisit(self,p,d,path,results):
  355.         pass
下面是用binary tree来做表达式的解析:

点击(此处)折叠或打开

  1. class ExpressionTree(LinkedBinaryTree):
  2.     #An arithmetic expression tree
  3.     def __init__(self,token,left=None,right=None):
  4.         #create an expression tree
  5.         super().__init__() #LinkedBinaryTree initialization
  6.         if not isinstance(token,str):
  7.             raise TypeError("Token must be a string")
  8.         self._add_root(token) #use inherited,non public method
  9.         if left is not None: #presumably three-parameter form
  10.             if token not in "+-*x/":
  11.                 raise ValueError("token must be valid operator")
  12.             self._attach(self.root(),left,right) #use inherited,nonpublic method

  13.     def __str__(self):
  14.         #return string representation of the expression
  15.         pieces=[] #sequence of piecewise strings to compose
  16.         self._parenthesize_recur(self.root(),pieces)
  17.         return "".join(pieces)

  18.     def _parenthesize_recur(self,p,result):
  19.         #append piecewise representation of p subtree to resulting list
  20.         if self.is_leaf(p):
  21.             result.append(str(p.element())) #leaf value as a string
  22.         else:
  23.             result.append("(") #opening parenthesis
  24.             self._parenthesize_recur(self.left(p),result) #left subtree
  25.             result.append(p.element()) #operator
  26.             self._parenthesize_recur(self.right(p),result) #right subtree
  27.             result.append(")") #closing parenthesis

  28.     def evaluate(self):
  29.         #return the numeric result of the expression
  30.         return self._evaluate_recur(self.root())

  31.     def _evaluate_recur(self,p):
  32.         #return the numeric result of subtree rooted at p
  33.         if self.is_leaf(p):
  34.             return float(p.element()) #we assume element is numeric
  35.         else:
  36.             op=p.element()
  37.             left_val=self._evaluate_recur(self.left(p))
  38.             right_val=self._evaluate_recur(self.right(p))
  39.             if op=="+": return left_val + right_val
  40.             elif op=="-": return left_val - right_val
  41.             elif op=="/": return left_val / right_val
  42.             else:
  43.                 return left_val * right_val

  44. def build_expression_tree(tokens):
  45.     #return an expression Tree based upon by a tokenized expression
  46.     S=[] #use list as stack
  47.     for t in tokens:
  48.         if t in "+-*x/": #t is an operator symbol
  49.             S.append(t) #push the operator symbol
  50.         elif t not in "()": #consider t to be a literal
  51.             S.append(ExpressionTree(t)) #push trivial tree storing value
  52.         elif t==")": #compose a new tree from three constituent parts
  53.             right=S.pop() #right subtree as per LIFO
  54.             op=S.pop() #operator symbol
  55.             left=S.pop() #left subtree
  56.             S.append(ExpressionTree(op,left,right)) #repush tree

  57.     return S.pop()


  58. def test_buil_exp_tree():
  59.     exp="(((3+1)x4)/((9-5)+2))"
  60.     exp_tree=build_expression_tree(exp)
  61.     print(exp_tree)
  62.     print(exp_tree.evaluate())


  63. test_buil_exp_tree()

阅读(1974) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~