アルゴリズム日記 2022/09/29

9月29日

今日はバイナリサーチでツリーの中身を表示するメソッドを作成します。
こんな感じでルートノードから下に向かってツリーの中身を出力します。

......................................................
                                50                                                              
                25                              75                              
        12              37              --              87              
    --      --      30      43      --      --      --      93      
  --  --  --  --  --  33  --  --  --  --  --  --  --  --  --  97  
......................................................

javaのプログラムは以下の通り
Stackを利用しています。
bashにはStackがないのでメソッドを自作する必要がありそう
Stackも配列の操作なのでbashの配列操作を使ってメソッドを作成します。
配列操作の基本については鈴木維一郎先生が作成したページを参考にしてください。
https://suzukiiichiro.github.io/posts/2022-09-27-01-array-suzuki/

   public void displayTree()
      {
      Stack globalStack = new Stack();
      globalStack.push(root);
      int nBlanks = 32;
      boolean isRowEmpty = false;
      System.out.println(
      "......................................................");
      while(isRowEmpty==false)
         {
         Stack localStack = new Stack();
         isRowEmpty = true;

         for(int j=0; j<nBlanks; j++)
            System.out.print(' ');

         while(globalStack.isEmpty()==false)
            {
            Node temp = (Node)globalStack.pop();
            if(temp != null)
               {
               System.out.print(temp.iData);
               localStack.push(temp.leftChild);
               localStack.push(temp.rightChild);

               if(temp.leftChild != null ||
                                   temp.rightChild != null)
                  isRowEmpty = false;
               }
            else
               {
               System.out.print("--");
               localStack.push(null);
               localStack.push(null);
               }
            for(int j=0; j<nBlanks*2-2; j++)
               System.out.print(' ');
            }  // end while globalStack not empty
         System.out.println();
         nBlanks /= 2;
         while(localStack.isEmpty()==false)
            globalStack.push( localStack.pop() );
         }  // end while isRowEmpty is false
      System.out.println(
      "......................................................");
      }  // end displayTree()
// -------------------------------------------------------------
   }  // end class Tree

スタックは後入れ先出しです。
pushで配列の後ろに要素を追加し、popで配列の一番後ろに入れた要素を取り出します。
isEmptyという配列が空になったかを判定するメソッドも必要です。
popで最後の配列要素をechoし、unsetで最後の配列要素を削除しようとしたのですが、
current=$(localStack.pop)という形で呼び出すと、サブシェルで呼び出すのでechoで最後の要素の内容は受け取れるのですが、unsetの結果が反映されませんでした。
しょうがないので最後の配列要素をechoするpeekメソッドを作り、popは、unsetだけする動作に変更しました。

function Stack_global.push() {
    Stack_global+=($1)
}

function Stack_global.pop() {
    if [ ${#Stack_global[*]} == 0 ];then
      echo "null";
      return;
    fi
    local el=${Stack_global[${#Stack_global[*]}-1]}
    po=$((${#Stack_global[*]}-1))
    unset Stack_global[$po]
}
function Stack_global.peek() {
    if [ ${#Stack_global[*]} == 0 ];then
      echo "null";
      return;
    fi
    local el=${Stack_global[${#Stack_global[*]}-1]}
    po=$((${#Stack_global[*]}-1))
    echo $el
}
function Stack_global.isEmpty() {
  if [ ${#Stack_global[*]} == 0 ];then
    echo "true";
  else
    echo "false"
  fi
}


bashのプログラムは以下の形になります。


   public void displayTree()
      {
      Stack globalStack = new Stack();
      globalStack.push(root);
      int nBlanks = 32;
      boolean isRowEmpty = false;
      System.out.println(
      "......................................................");
      while(isRowEmpty==false)
         {
         Stack localStack = new Stack();
         isRowEmpty = true;

         for(int j=0; j<nBlanks; j++)
            System.out.print(' ');

         while(globalStack.isEmpty()==false)
            {
            Node temp = (Node)globalStack.pop();
            if(temp != null)
               {
               System.out.print(temp.iData);
               localStack.push(temp.leftChild);
               localStack.push(temp.rightChild);

               if(temp.leftChild != null ||
                                   temp.rightChild != null)
                  isRowEmpty = false;
               }
            else
               {
               System.out.print("--");
               localStack.push(null);
               localStack.push(null);
               }
            for(int j=0; j<nBlanks*2-2; j++)
               System.out.print(' ');
            }  // end while globalStack not empty
         System.out.println();
         nBlanks /= 2;
         while(localStack.isEmpty()==false)
            globalStack.push( localStack.pop() );
         }  // end while isRowEmpty is false
      System.out.println(
      "......................................................");
      }  // end displayTree()
// -------------------------------------------------------------
   }  // end class Tree

Stackをglobal,localの2つを使っています。
push,pop,isEmpty,peekのメソッドをそれぞれ個別に作成しましたが、evalで1つにまとめた方が良いかもしれません。

書籍の紹介

【アルゴリズム 配列準備編】ざっくりわかるシェルスクリプト7

【アルゴリズム 配列準備編】ざっくりわかるシェルスクリプト7

【アルゴリズム 配列編】ざっくりわかるシェルスクリプト6

【アルゴリズム 配列編】ざっくりわかるシェルスクリプト6