简体   繁体   English

Python 中用二叉树进行摩尔斯编码

[英]Morse Encoding with Binary Tree in Python

I am trying to code a program that encodes/decodes Morse Code using a binary tree.我正在尝试编写一个使用二叉树编码/解码摩尔斯电码的程序。 Initially my code worked by taking an input when run and successfully converted it to Morse code.最初我的代码通过在运行时获取输入并成功将其转换为摩尔斯电码来工作。

However, I am trying to make it so that the terminal command encode('xyz') will take the xyz string and convert to the Morse, returning the result.但是,我试图做到这一点,以便终端命令encode('xyz')将采用 xyz 字符串并转换为摩尔斯电码,并返回结果。 To do this, I have had to rejig the code, and am now running into errors.为此,我不得不重新调整代码,现在遇到了错误。 Is there something obvious I am missing?有什么明显的我想念的吗?

class BTree: 
    def __init__(self, data=None, left=None, right=None):
        self.data = data
        self.left = left 
        self.right = right 

    def insert(self, data):
        if self.data:
            if data < self.data:
                if self.left:
                    self.left.insert(data)
                else: 
                    self.left = BTree(data) 
            elif data > self.data: 
                if self.right:
                    self.right.insert(data) 
                else:
                    self.right = BTree(data) 
        else:
            self.data = data

    def output(self): 
        if self.left:
            self.left.output() 
        print(self.data) 
        if self.right: 
            self.right.output() 

    def encode(self, msg: str):
        dotsdashes = []
        code = "".join(dotsdashes)

        for character in msg:
            self.getMorse(code, character, dotsdashes)
            morseCode = morseCode + code + " "

    def getMorse(self, node, character, code):
        if node==None:
            return False
        elif node.data == character:
            return True
        else:
            if self.getMorse(node.left,character,code) == True:
                code.insert(0,".")
                return True
            elif self.getMorse (node.right,character,code)==True:
                code.insert(0,"-")
                return True 

My main function (won't format properly when copied and pasted as one):我的主要 function(复制并粘贴时格式不正确):

if __name__ == '__main__':
    root = BTree("Root")
    root.left = BTree("E")
    root.right = BTree("T")
    root.left.left = BTree("I")
    root.left.right = BTree("A")
    root.right.left = BTree("N")
    root.right.right = BTree("M")
    root.left.left.left = BTree("S")
    root.left.left.right = BTree("U")
    root.left.right.left = BTree("R")
    root.left.right.right = BTree("W")
    root.right.left.left = BTree("D")
    root.right.left.right = BTree("K")
    root.right.right.left = BTree("G")
    root.right.right.right = BTree("O")
    root.left.left.left.left = BTree("H")
    root.left.left.left.right = BTree("V")
    root.left.left.right.left = BTree("F")
    root.left.left.right.right = BTree("")
    root.left.right.left.left = BTree("L")
    root.left.right.left.right = BTree("")
    root.left.right.right.left = BTree("P")
    root.left.right.right.right = BTree("J")
    root.right.left.left.left = BTree("B")
    root.right.left.left.right = BTree("X")
    root.right.left.right.left = BTree("C")
    root.right.left.right.right = BTree("Y")
    root.right.right.left.left = BTree("Z")
    root.right.right.left.right = BTree("Q")
    root.right.right.right.left = BTree("")
    root.right.right.right.right = BTree("")

Also wondering if populating the binary tree in the main function rather than it's own function was the right thing to do?还想知道在主 function 而不是它自己的 function 中填充二叉树是否正确?

I'm relatively new to using binary trees so apologies for the potentially poor explanation/silly question.我对使用二叉树还比较陌生,所以对于可能解释不当/愚蠢的问题深表歉意。

EDIT: I should have included that the most recent error I am getting is: line 41, in getMorse elif node.data == character: AttributeError: 'str' object has no attribute 'data'编辑:我应该包括我得到的最新错误是:第 41 行,在 getMorse elif node.data == character: AttributeError: 'str' object has no attribute 'data'

There are these issues:有这些问题:

  • In morseCode = morseCode + code + " " you reference morseCode on the right side of the assignment, but it was never initialised with a value.morseCode = morseCode + code + " "中,您在赋值的右侧引用morseCode ,但它从未用值初始化。 So you need to initialise it before the loop with the empty string所以你需要在循环之前用空字符串初始化它

  • In the call self.getMorse(code, character, dotsdashes) you pass a string code as first argument, but the function expects a node there.在调用self.getMorse(code, character, dotsdashes)时,您传递一个字符串code作为第一个参数,但 function 需要一个节点。 So you should pass self as argument instead of code所以你应该将self作为参数而不是code传递

  • self.getMorse returns a boolean, but in the above call you never look at this boolean. You should probably do something when that returned value is false. self.getMorse返回一个 boolean,但在上面的调用中你永远不会看到这个 boolean。当返回值为 false 时,你可能应该做一些事情。

  • code = "".join(dotsdashes) is happening too soon (and only once). code = "".join(dotsdashes)发生得太快了(而且只有一次)。 This should happen in the loop after you made the call to self.getMorse as only then dotsdashes will have been populated.这应该在您调用self.getMorse之后在循环中发生,因为只有这样才会填充dotsdashes

  • dotsdashes = [] should happen each time before you call self.getMorse , as otherwise it will just accumulate the new morse code adjacent to what it already had from a previous iteration. dotsdashes = []应该在每次调用self.getMorse之前发生,否则它只会将新的莫尔斯电码累积到与上一次迭代已经拥有的电码相邻的位置。

  • encode should return the result. encode应该返回结果。

Here is a correction of that encode function:这是该encode function 的更正:

    def encode(self, msg: str):
        morseCode = ""  # Init
        for character in msg:
            dotsdashes = []  # Moved inside the loop
            success = self.getMorse(self, character, dotsdashes) # Change first argument
            if not success:  # Deal with return value
                raise ValueError(f"Invalid character - no Morse code available for {character}")
            code = "".join(dotsdashes)  # Moved inside the loop
            morseCode = morseCode + code + " "
        return morseCode  # Return

Remarks:评论:

  • It seems overkill to really create a tree for this.真的为此创建一棵树似乎有点过分了。 A dictionary seems more appropriate: it requires less code and will not need to walk through a tree to find a character, which could be anywhere.字典似乎更合适:它需要更少的代码,并且不需要遍历树来查找可能在任何地方的字符。
  • It is not best practice to pass a list as third argument to self.getMorse , which it populates.将列表作为第三个参数传递给它填充的self.getMorse不是最佳做法。 Better is to make that the return value, and to return None if there is no Morse code available.更好的做法是将其作为返回值,如果没有可用的摩尔斯电码则返回None
  • The insert method implements a binary search tree, which is not what you need here. insert方法实现了一个二叉搜索树,这不是你在这里需要的。 It should not be included in your class.它不应包含在您的 class 中。

Alternative tree替代树

The tree you have created is acomplete binary tree (even a perfect one), so you can encode that tree in a list (as is often done for binary heaps ).您创建的树是一棵完整的二叉树(甚至是完美的二叉树),因此您可以在列表中对该树进行编码(就像对二叉堆所做的那样)。 And since the data for each node is just a character, it could be a string instead of a list.由于每个节点的数据只是一个字符,它可以是一个字符串而不是一个列表。

The binary representation of an index in that string could then be made to be the Morse code (where 0,1 maps to dot,dash respectively) of the character at that index.然后可以使该字符串中索引的二进制表示成为该索引处字符的摩尔斯电码(其中 0,1 分别映射到点、破折号)。 To make sure that all binary 0 are included in the binary representation, even when they occur before any 1, we can go for binary representations where the first 1 is ignored, and all other binary digits represent the actual Morse code.为了确保所有二进制 0 都包含在二进制表示中,即使它们出现在任何 1 之前,我们可以将 go 用于二进制表示,其中第一个 1 被忽略,所有其他二进制数字代表实际的摩尔斯电码。

This leads to the following code, which is still tree-based:这导致以下代码,它仍然是基于树的:

MORSE = "..ETIANMSURWDKGOHVF.L.PJBXCYZQ"

def encode_char(c):
    return bin(MORSE.index(c))[3:].replace("0", ".").replace("1", "-")

def encode(s):
    return " ".join(map(encode_char, s))

print(encode("SOS"))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM