python自学日记26——二叉树(中序遍历去括号)

python自学日记26——二叉树(中序遍历去括号)

1.解析树:中序遍历法去括号

将数学表达式表示成解析树

from pythonds.basic import Stack
from pythonds.trees import BinaryTree

def buildParseTree(fpexp):
    fplist=fpexp.split()
    pStack=Stack()
    eTree=BinaryTree('')
    pStack.push(eTree)
    currentTree=eTree
    for i in fplist:
        if i=='(':
            currentTree.insertLeft('')
            pStack.push(currentTree)
            currentTree=currentTree.getLeftChild()
        elif i not in '+-*/)':
            currentTree.setRootVal(eval(i))
            parent=pStack.pop()
            currentTree=parent
        elif i in '+-*/':
            currentTree.setRootVal(i)
            currentTree.insertRight('')
            pStack.push(currentTree)
            currentTree=currentTree.getRightChild()
        elif i==')':
            currentTree=pStack.pop()
        else:
            raise ValueError('Unknown Operator:'+i)
    return eTree
parseTree=buildParseTree('( 3 + ( 4 * 5 ) )')

这个没什么问题,主要想记录的是后面的中序遍历法:

def inorder(tree):
    if tree!=None:
        inorder(tree.getLeftChild())
        print(tree.getRootVal())
        inorder(tree.getRightChild())
inorder(parseTree)

这个将返回的是

3

4

5

修改上述使得能还原完全括号表达式

def printexp(tree):
    sVal=''
    if tree:
        sVal='('+printexp(tree.getLeftChild())
        sVal=sVal+str(tree.getRootVal())
        sVal=sVal+printexp(tree.getRightChild())+')'
    return sVal
printexp(parseTree)

返回值:’((3)+((4)*(5)))’,这里面不必要的括号太多了,想着如何去掉,在添加左括号时想着如果没有右子树,那么就不用加括号,添加右括号时如果没有左括号就不用了

def printexp(tree):
    sVal=''
    if tree:
        if tree.getRightChild()!=None:
            sVal='('+printexp(tree.getLeftChild())
        else:
            sVal=printexp(tree.getLeftChild())
        sVal=sVal+str(tree.getRootVal())
        if tree.getLeftChild()!=None:
            sVal=sVal+printexp(tree.getRightChild())+')'
        else:
            sVal=sVal+printexp(tree.getRightChild)
    return sVal
printexp(parseTree)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-51-41c5c2f524fd> in <module>
     13             sVal=sVal+printexp(tree.getRightChild)
     14     return sVal
---> 15 printexp(parseTree)

<ipython-input-51-41c5c2f524fd> in printexp(tree)
      4     if tree:
      5         if tree.getRightChild()!=None:
----> 6             sVal='('+printexp(tree.getLeftChild())
      7         else:
      8             sVal=printexp(tree.getLeftChild())

<ipython-input-51-41c5c2f524fd> in printexp(tree)
     11             sVal=sVal+printexp(tree.getRightChild())+')'
     12         else:
---> 13             sVal=sVal+printexp(tree.getRightChild)
     14     return sVal
     15 printexp(parseTree)

<ipython-input-51-41c5c2f524fd> in printexp(tree)
      3     sVal=''
      4     if tree:
----> 5         if tree.getRightChild()!=None:
      6             sVal='('+printexp(tree.getLeftChild())
      7         else:

AttributeError: 'function' object has no attribute 'getRightChild'

后面想要不从根节点开始判断:

def printexp(tree):
    sVal=''
    if tree.getRightChild():
        sVal='('+printexp(tree.getLeftChild())
        sVal=sVal+str(tree.getRootVal())
        sVal=sVal+printexp(tree.getRightChild())+')'
    else:
        sVal=printexp(tree.getLeftChild())
        sVal=sVal+str(tree.getRootVal())
        sVal=sVal+printexp(tree.getRightChild())
    return sVal
printexp(parseTree)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-64-83baf66c77ef> in <module>
     10         sVal=sVal+printexp(tree.getRightChild())
     11     return sVal
---> 12 printexp(parseTree)

<ipython-input-64-83baf66c77ef> in printexp(tree)
      2     sVal=''
      3     if tree.getRightChild():
----> 4         sVal='('+printexp(tree.getLeftChild())
      5         sVal=sVal+str(tree.getRootVal())
      6         sVal=sVal+printexp(tree.getRightChild())+')'

<ipython-input-64-83baf66c77ef> in printexp(tree)
      6         sVal=sVal+printexp(tree.getRightChild())+')'
      7     else:
----> 8         sVal=printexp(tree.getLeftChild())
      9         sVal=sVal+str(tree.getRootVal())
     10         sVal=sVal+printexp(tree.getRightChild())

<ipython-input-64-83baf66c77ef> in printexp(tree)
      1 def printexp(tree):
      2     sVal=''
----> 3     if tree.getRightChild():
      4         sVal='('+printexp(tree.getLeftChild())
      5         sVal=sVal+str(tree.getRootVal())

AttributeError: 'NoneType' object has no attribute 'getRightChild'

结果还是报错

def printexp(tree):
    sVal=''
    if tree:
        if type(tree.getRightChild())!='NoneType':
            sVal='('+printexp(tree.getLeftChild())
        else:
            sVal=printexp(tree.getLeftChild())
        sVal=sVal+str(tree.getRootVal())
        if type(tree.getLeftChild())!='NoneType':
            sVal=sVal+printexp(tree.getRightChild())+')'
        else:
            sVal=sVal+printexp(tree.getRightChild)
    return sVal
printexp(parseTree)

如果子节点没有就不用加括号,然后返回的结果还是一样的’((3)*((4)+(5)))’,我看这段代码以为我添加括号的地方写错了位置,我其实都有点放弃这个问题了,想着以后如果能想出来再说,结果误打误撞发现了转机

def printexp(tree):
    sVal=''
    if tree:
        if type(tree.getRightChild())!='NoneType':
            sVal=printexp(tree.getLeftChild())
        else:
            sVal='('+printexp(tree.getLeftChild())
        sVal=sVal+str(tree.getRootVal())
        if type(tree.getLeftChild())!='NoneType':
            sVal=sVal+printexp(tree.getRightChild())
        else:
            sVal=sVal+printexp(tree.getRightChild)+')'
    return sVal
printexp(parseTree)

将添加括号的位置放到else里来后发现返回值是3+4*5,我还以为成功了呢,结果将公式替换为

parseTree=buildParseTree('( 3 * ( 4 + 5 ) )')

返回的结果是3*4+5,那么就说明代码还是有问题,然后又想应该是同时有左子树和右子树时才加括号,代码修改如下:

def printexp(tree):
    sVal=''
    if tree:
        if str(type(tree.getLeftChild()))!='NoneType' and str(type(tree.getRightChild()))!='NoneType':
            sVal='('+printexp(tree.getLeftChild())
            sVal=sVal+str(tree.getRootVal())
            sVal=sVal+printexp(tree.getRightChild())+')'
        else:
            sVal=printexp(tree.getLeftChild())
            sVal=sVal+str(tree.getRootVal())
            sVal=sVal+printexp(tree.getRightChild())

    return sVal
printexp(parseTree)

因为type类型是NoneType,想着是不是需要改成字符串和后面的才有比较性,后来发现用str改后返回值是"<class 'pythonds.trees.binaryTree.BinaryTree'>",还是不行。最后发现也许是自己想的过于复杂了,下午的思路还是影响自己,晚上过了这么久后发现好像换个思路应该可以

def printexp(tree):
    sVal=''
    if tree:
        if tree.getLeftChild() and tree.getRightChild():
            sVal='('+printexp(tree.getLeftChild())
            sVal=sVal+str(tree.getRootVal())
            sVal=sVal+printexp(tree.getRightChild())+')'
        else:
            sVal=printexp(tree.getLeftChild())
            sVal=sVal+str(tree.getRootVal())
            sVal=sVal+printexp(tree.getRightChild())

    return sVal
printexp(parseTree)

返回值就正常了:(3*(4+5)),这样看确实如“python自学日记16——调试(常见错误)”中所说,遇到问题实在做不出来可以过段时间再想,也许就做出来了。

本来想把这个问题写出来问下大家的,结果自己写着写着就找到解决方案了。

2.cannot import name ‘BinaryHeap’ from ‘pythonds.trees’

这次说一个bug,在导入二叉堆的时候发现:

from pythonds.trees import BinaryHeap

会报错:

ImportError:cannot import name 'BinaryHeap' from 'pythonds.trees' (D:\anaconda\lib\site-packages\pythonds\trees\__init__.py)

遇到这种错误第一想法就是搜索引擎查一下,发现没找到合适的答案,涉及导入模块一般要么pip 安装一下,但是这个跟以往的有点区别,以往都是报错没有xx模块,但是这个还给出了路径,我就想着去这个路径里看看,发现没有BinaryHeap,但是有BinHeap,看到这就明白是改版了,换成新的名称了。后面可以记住如果再遇到有提供路径的,可以去路径里查看下原因。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值