文字列計算機をエレガントに書く方法(JAVA)

文字列計算機

Coordinates 2020-4-24
pass-Huawei two side。
インタビュアーはダイナミックな写真を見せて、私に尋ねました:20分で簡単な文字列計算機を書けますか?
少し考えてみてください。大丈夫です。
それでは、混乱の中で、再帰を使用すると同時にスタックも使用したいと思います。最後に、ヌルポインターの異常が無数にある計算機を作成しました。その後、苦痛から学び、今日は文字列計算機の作成方法を説明します。

まず、文字が数字かどうかを判断する関数が必要です。

 public static boolean isNum(char x){
    
    
        return x>=48 && x<=57;
    }//利用ascall码判断是否为数字

それで、アルゴリズムのアイデアを設計する2番目のステップに進みます。
文字列計算機の問題解決のアイデアについては、インターネット上で1つしか見られませんでした。これは、ポーランド語のインフィックス式を使用してサフィックスに変換し、1つずつ計算することです。インタビューの過程で、最初の反応は、再帰を使用してすべての括弧を減らし、次に乗算と除算、加算と減算の順に計算することでした。今日は両方のアイデアを改善します。

アイデア1:ポーランド語の式
最初に、次の式2 + 3 *(6-2)を確認します。入力する式であるこの式は、ポーランド語のインフィックス式です。後置式に変換して、 2 3 6 2- * +
どのようなルールを見つけましたか?つまり、演算子を操作の順序で番号の後に配置します。計算するときは、支援するスタックのみが必要であり、結果を順番に計算できます。アップ。
何人かの友人は言った、私はその考えを理解している、それをどのように書くか?ゆっくり話させてください。

最初のステップでは、いくつかの補助ツールが必要
です。1。文字列

StringBuilder stringBuilder = new StringBuilder();

StringBuilderを使用して、変換されたサフィックス式を格納します。

2.スタック

Stack<Character> stack = new Stack<>();

スタックを使用してストレージを支援します。

3.元の表現の文字形式

char x[] = str.toCharArray();

関数に渡された文字列を文字配列に変換するので、isNum関数を使用して判断すると便利です。

これで、関数は次のようになります

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        retrun null;
        }

次に、文字配列全体をトラバースします

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    

        }
        retrun null;
        }

考えてみてください。アレイをトラバースするときに何をすべきでしょうか。
いくつかの状況があります:
1。現在の文字は数字です
2.現在の文字は演算子です
3.現在の文字は括弧です

ケース1の場合、最終的な接尾辞式では番号が元の順序で配置されているため、結果に追加するだけで済みます。

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
     //该字符为数字,直接加入结果
                stringBuilder.append(x[i]);
                continue;
            }
        }
        retrun null;
        }

一部の学生は言った:複数の桁がある場合はどうなりますか?いくつかの改善を行います

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
     //该字符为数字,直接加入结果
                stringBuilder.append(x[i]);
                if ((i<x.length-1&&!isNum(x[i+1]))||i==x.length-1)){
    
    
                    stringBuilder.append(" ");
                }
                continue;
            }
        }
        retrun null;
        }

このステップでは、結果に番号を追加して判断します。現在の文字がすでに最後の文字である場合は、その後にスペースを追加するか、現在の文字の次の文字が番号でない場合は、それも追加します。その後にスペースを追加します。

ケース2と3の場合
、操作中は/記号の優先度が±より高いため最初に/を処理し、* /に遭遇すると、補助スタックに配置します

 if (x[i]=='*'||x[i]=='/'){
    
    
                stack.push(x[i]);
                continue;
            }

括弧は乗算や除算よりも優先されます。どうすればよいですか?
スタックの特性を考えると、左括弧に出会ったらスタックに入る必要があり、とりあえず次のように掛け算や割り算と同じレベルだと思います。

 if (x[i]=='*'||x[i]=='/'||x[i]=='('){
    
    
                stack.push(x[i]);
                continue;
            }

左の括弧に遭遇した後も、括弧の一致ルールである右の括弧が見つかるまで元の論理操作を実行します。
この時点で、スタックを操作し、対応する右の括弧が見つかるまでスタックをループアウトする必要があります。括弧を開くと、括弧内の変換が完了しました。

if (x[i]==')'){
    
    
                while (!stack.isEmpty()){
    
    
                    if (stack.peek()=='('){
    
    
                        stack.pop();
                        continue;
                    }
                    stringBuilder.append(stack.pop());
                }
                continue;
            }

一部の学生は、それがあまり鮮やかだとは思わないかもしれません。
閉じ括弧の前に(3 + 4)スタックの内容をシミュレートしましょう。スタック
の内容は(+
で、文字列の内容は3 4です。
スタックをポップした後文字列の内容内容は34 +に
なり、スタックの括弧内に演算子はありません。
この時点で、括弧内の接尾辞の変換は完了しています。

現時点では、バーは問題ありません(取り消し線が引かれています)。生徒たちは、加算と減算についてはどうでしょうか。
加算と減算が発生する場合、いくつかの状況を考慮する必要があり
ます。1。現在のスタックが空で、シンボルが直接スタックに配置されます
。2。現在のスタックが空ではなく、スタックの最上位要素が(、±が括弧内の演算子であることを示します。また、直接スタックに
3。現在のスタックは空ではなく、スタックの最上位要素は空ではありません(これは、±が括弧内にある可能性があることを示していますが、現在の操作順序±は、スタックをポップした後、スタックの最上位要素の後ろに配置する必要があります。 ±スタックに入れる

if (x[i]=='+'||x[i]=='-'){
    
    
               while (!stack.isEmpty()&&stack.peek()!='('){
    
    
                   stringBuilder.append(stack.pop());
               }
               stack.push(x[i]);
               continue;
            }

最後に、returnステートメントを追加して後置式を取得します

return stringBuilder.toString();

完全な機能は次のとおりです

public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
    
                stringBuilder.append(x[i]);
                if (((i<x.length-1&&!isNum(x[i+1]))||i==x.length-1)){
    
    
                    stringBuilder.append(" ");
                }
                continue;
            }
            if (x[i]=='*'||x[i]=='('||x[i]=='/'){
    
    
                stack.push(x[i]);
                continue;
            }
            if (x[i]==')'){
    
    
                while (!stack.isEmpty()){
    
    
                    if (stack.peek()=='('){
    
    
                        stack.pop();
                        continue;
                    }
                    stringBuilder.append(stack.pop());
                }
                continue;
            }
            if (x[i]=='+'||x[i]=='-'){
    
    
               while (!stack.isEmpty()&&stack.peek()!='('){
    
    
                   stringBuilder.append(stack.pop());
               }
               stack.push(x[i]);
               continue;
            }

        }
        return stringBuilder.toString();
    }

次のステップは、接尾辞式の結果を計算することです。このステップは非常に簡単です。説明はしません。番号をスタックにプッシュし、オペレーターに遭遇したときにスタックをポップし、計算結果を取得した後でスタックを再度プッシュするだけです。
注/および-正しい結果を計算するには、スタックからポップされた2つの番号の順序を逆にする必要があります

public static Integer help(String str){
    
    
        Stack<Integer> num = new Stack<>();
        StringBuilder stringBuilder = new StringBuilder();
        char x[] = str.toCharArray();
        for (int i =0;i<x.length;i++){
    
    
            if (isNum(x[i])){
    
    
                stringBuilder.append(x[i]);
                if (i+1==x.length){
    
    
                    num.push(Integer.parseInt(stringBuilder.toString()));
                }
                if (x[i+1]==' '){
    
    
                    num.push(Integer.parseInt(stringBuilder.toString()));
                    stringBuilder.delete(0,stringBuilder.length());
                    continue;
                }
            }
            if (x[i]=='+'){
    
    
                num.push(num.pop()+num.pop());
            }
            if (x[i]=='-'){
    
    
                int a = num.pop();
                int b = num.pop();
                num.push(b-a);
            }
            if (x[i]=='*'){
    
    
                num.push(num.pop()*num.pop());
            }
            if (x[i]=='/'){
    
    
                int a = num.pop();
                int b = num.pop();
                num.push(b/a);
            }
        }
        return num.pop();
    }

このようにして、main関数で2つの関数を呼び出して、最終的な計算結果を取得します。

再帰については、2番目の記事を参照してください。

おすすめ

転載: blog.csdn.net/qq_45789385/article/details/105733553