二分木の単純なアプリケーション式ツリー

二分木の簡単なアプリケーション:式ツリー

このアプリケーションは、主に二分木の構造を使用します。

数式がある場合:(2-3)*(4 + 5)

括弧と優先順位の概念を放棄し、記号の順序のみを変更します** ∗ − 23 + 45 * -23 + 452 3+4 5 **

式ではオペレーターアドバンスアップ、各演算子の後には2つのオペランドが続きます、左から右にトラバースして唯一の計算ステップを取得します。これはポーランド式です。

次のインフィックス式がある場合:

(2-3)*(4 + 5)

接頭辞と接尾辞の式をすばやく見つけるために、最初に次の括弧を完成させます。

((2-3)*(4 + 5))

次に、次のように、対応する開き括弧の前にすべての演算子を配置します。

* (-(2 3)+(4 5))

最後に、括弧を削除して、次のようになります。

***-2 3 + 4 5 **

これはプレフィックス式であり、同様にポストフィックス式を取得できます。

1.バイナリ式とバイナリツリー

数式(算術式)は階層的な再帰構造を持っています。演算子は対応するオペランドに作用し、そのオペランドは任意の複雑な式にすることができます。バイナリツリーの再帰構造は、この種の式を表現するために使用されます。関係バイナリツリーのノードとサブツリーの間は、演算子とオペランドの関係を表すために使用できます。

二項演算子のみを含む式は二項式と呼ばれます。実際、ここで提案するカウントの適用範囲は二項式をはるかに超えており、一般的な数式や論理式などを表現するために使用できます。式は特殊なケースです。基本式がすべて数値である二項数式の。

二分木は自然に二分木にマッピングできます

  • リーフノードのデータとして基本的なオペランド(数値と変数)を使用する
  • 演算子をブランチノードとするデータ
    • その2つのサブツリーはそのオペランドです
    • サブツリーは、基本オペランドまたは任意の複雑なバイナリ式にすることができます

[外部リンク画像の転送に失敗しました。ソースサイトにヒル防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-yLELqGGt-1610447298310)(C:\ Users \ 93623 \ AppData \ Roaming \ Typora \ typora-user-images \ image-20210112163727645.png)]

正しく構造化されたバイナリ式は、完全なバイナリツリーに対応します

最初のルート順序トラバーサル:x-ab + / cde式のプレフィックス表現(ポーランド式)

ルート順序トラバーサル後:ab-cd / e + x式のインフィックス表現(逆ポーランド式)

ミドルルートオーダートラバーサル:a-bxc / d + e式の接尾辞表現

2.式の作成

確立された数式は変更されないため、数式と演算は既存の式に基づいて新しい式を作成します。したがって、合理的な方法は、それを「不変」の二分木として実装することです。Pythonのタプルは、実装の基礎として使用されます。三元タプルは、二分木ノードを実装するために使用されます

関連する表現をより簡潔かつ明確にするために、上記で提案したバイナリツリーの表現に少し変更を加えます。バイナリ式に対応するタプルでは、​​基本的な操作オブジェクト(数値または変数)が直接配置されます。基本オブジェクトとしての空の木の位置。式3 ∗(2 + 5)3 *(2 + 5)32+5 二分木に直接マッピングされている

( '*'、(3、None、None)、( '+'、(2、None、None)、(5、None、None)))

これは、実用的な意味を持たないNoneが常に多数存在することを意味します。この状況を回避するために、以下は括弧付きのプレフィックス式に簡略化され、括弧は演算子のスコープを示します。

( '*'、3、( '+'、2、5))

この変更された式では、式は2つの構造で構成されます。

  • タプルの場合、演算子がオペランドに作用する複合式です。
  • それ以外の場合は、基本的な式、つまり数値または変数です。

上記の2つを使用して、式の構造を分析し、式の処理を実現できます。

# 定义几个表达式构造函数
def make_sum(a,b):
    return ('+', a, b)

def make_pro(a,b):
    return ('*', a, b)

def make_diff(a,b):
    return ('-', a, b)

def make_div(a, b):
    return ('/', a, b)


次のステートメントは、単純な算術式を作成します。

el = make_pro(3、make_sum(2,5))

明らかに、この構造を使用すると、複雑な構造で式を作成でき、文字列を使用して変数を表し、次のようなさまざまな代数式を作成できます。

make_sum(make_prod( 'a'、a)、make_prod( 'b'、7))

式処理関数を定義するとき、基本式(直接処理)と複合式(再帰処理)を区別する必要があることがよくあります。これら2つの状況を区別するために、関数を定義して、それが基本式であるかどうかを判別します。

def is_basic_exp(a):
	return not isinstance(a, tuple)

def is_number(x):
    return (isinstance(x, int) or isinstance(x, float) isinstance(x,complex))

3.式の評価

上で定義した2進式は、単純な数式のPython実装です。これらの定義に基づいて、必要に応じてさまざまな式操作を実装できます。たとえば、2つの2進式を合計するPython関数を定義できます。製品など、ここで検討します。式の値を見つける関数。

式の評価のルール:

  • 式の数値と変数の場合、それらの値はそれ自体です
  • 他の式は演算子の条件に従って処理され、特別な処理関数を定義できます
  • 演算子の2つのオペランドが数値の場合、値を見つけることができます

場合によっては、加数が0で、乗数が0または1の場合、関連する式のいくつかを評価して簡略化できます。つまり、いわゆる評価とは、式を簡単に簡略化して、[すべて計算]を計算することです。

評価関数の基本的な部分は次のとおりです。

def eval_exp(e):
    if is_basic_exp(e):
        return e
    op, a, b = e[0], eval_exp(e[1]), eval_exp(e[2]) # **
    if op == '+':
        return eval_sum(a,b)
    elif op == '-':
        return eval_diff(a,b)
    elif op == '*':
        return eval_prod(a, b)
    elif op == '/':
        return eval_div(a,b)
    else:
        raise ValueError("Unknown operator:", op)
        
def eval_sum(a, b):
    if is_number(a) and is_number(b):
        return a+b
    if is_number(a) and a == 0:
        return b
    if is_number(b) and b == 0:
        return a
    return make_sum(a,b)

def eval_div(a, b):
    if is_number(a) and is_number(b):
        return a / b
    if is_number(a) and a == 0:
        return 0
    if is_number(b) and b == 1:
        return a
    if is_number(b) and b == 0:
        raise ZeroDivisonError
    return make_div(a, b)

ここでの基本的な方法は、実際の演算子に基づいて特定の関数にさまざまな計算を分散することです。特に注目に値するのは、「**」とマークされたステートメントです。このステートメントでは、部分式がこの関数への2回の再帰呼び出しによって処理され、可能性が完成します。後で見ることができますが、バイナリツリーのすべての再帰処理はこのモードを使用します

最後の行で例外が発生すると、例外ValueErrorに対して2つの実際のパラメーターが提供されます。実際、例外が発生すると、任意の数の実際のパラメーターを送信できます。他の処理がない場合、例外情報はPythonインタープリターが例外情報を表示するときに出力されます。たとえば、上記の状況の場合、これらの実際のパラメーターの値は、文字列Unknown演算子とopの実際の値を出力します。キャッチして処理する場合このような例外は、Pythonが提供する特別なメカニズムを介してこれらの実際のパラメーターの値を取得できます。

例外の場合、例外ValueErrorに対して2つの実際のパラメーターが提供されます。実際、例外が発生すると、任意の数の実際のパラメーターを送信できます。他の処理がない場合は、Pythonインタープリターが例外を表示します。情報、これらの実際のパラメータが出力されます。値、たとえば、上記の状況では、文字列Unknown演算子とopの実際の値が出力されます。この例外をキャッチして処理する場合は、これらの実際の値を取得できます。 Pythonが提供する特別なメカニズムによるパラメータ。

おすすめ

転載: blog.csdn.net/weixin_46129834/article/details/112543628