List を正順(逆順)で印字

val= 9  val= 8  val= 7  val= 6  val= 5  val= 4  val= 3  val= 2  val= 1
val= 1  val= 2  val= 3  val= 4  val= 5  val= 6  val= 7  val= 8  val= 9

連鎖した List構造を、正順(逆順)に印字します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

List 構造

  1. 次のファイルを格納して下さい。
    /******************************************/
    /*★ 連鎖を正順(逆順)で印字     前田 稔 ★*/
    /******************************************/
    using System;
    
    class console
    {
        public static void Main()
        {   List    pt = new List();
    
            for (int i=1; i<10; i++) pt.Push(i);
            pt.BPrint();
            Console.WriteLine("");
            pt.Print();
        }
    }
    
    class List
    {
        public  int     val;    //セルの値
        public  List    ptr;    //セルのリンク
        public  List    top;    //List の先頭(最後に Push されたセル)
    
        //Constructor
        public List()
        {   ptr = null;
            top = null;
        }
        //List の先頭に追加
        public List Push(int v)
        {   List    wk;
            wk = new List();
            wk.val = v;
            wk.ptr = top;
            top = wk;
            return wk;
        }
        //List の先頭から(最後に Push された値)から印字
        public void BPrint()
        {   List    wk;
            for(wk=top; wk!=null; wk= wk.ptr)
                Console.Write("val= {0}  ",wk.val);
        }
        //List の後部から(登録された順)に印字
        public void Print()
        {   if (top!=null)   pnt(top);
        }
    
        //登録順に印字する再起関数
        void pnt(List pt)
        {   if (pt==null)   return;
            pnt(pt.ptr);
            Console.Write("val= {0}  ",pt.val);
            return;
        }
    }
    
  2. 「List の基礎」では、ループで連鎖する方法と、連鎖をたどって印字する方法を説明しました。
    説明したように、List は最後に格納されたセルを先頭に連鎖する方法が最もスマートです。
    従って連鎖をたどって印字すると、格納した順とは逆に印字されます。
  3. 今回は格納した順序どおりに印字してみましょう。
    先に説明したように、構築した List は最後のセルを先頭に一方向に連鎖されていて、逆方向にはたどれません。
    時には「双方向 List」を使って、正順/逆順にたどる方法もあるのですが、これはこれで List の構築が面倒です。
    そこで登場するのが再起関数です。
    Main() から正順に印字する Print() 関数を呼び出します。
    pt.Print();
  4. Print() 関数では top(最後に格納されたセル)を引数にして pnt() 関数を呼び出します。
        //List の後部から(登録された順)に印字
        public void Print()
        {   if (top!=null)   pnt(top);
        }
        
  5. 連鎖を登録順に印字する pnt() 関数です。
    ソースコードは極めてシンプルなのですが、どのようなロジックで登録順に印字しているか解りますか。 (^_^;)
    鍵は自分自身を呼び出す「pnt(pt.ptr)」にあります。
    この再起呼び出しは pt.ptr(pt から連鎖している prt)が null(終端)になるまで呼び続けます。
    終端に達すると pnt() 関数は return を実行して、一世代戻ります。
    そのときの pt.val を印字して return を実行して、もう一つ世代が戻ります。
        //登録順に印字する再起関数
        void pnt(List pt)
        {   if (pt==null)   return;
            pnt(pt.ptr);
            Console.Write("val= {0}  ",pt.val);
            return;
        }
        
  6. 再起のプログラムは、驚くほどシンプルなのですが、論理の流れは非常に難解です。
    再起が使えるようになると、プログラミングが一段と面白くなり、レパートリーも広がります。
    ぜひ再起のテクニックを習得して下さい。

超初心者のプログラム入門(C# Frame Work)