STEP 3.1 (ノーヒントバージョン) 

<問題> 配列による実装例。教科書とプログラムを読み、自分なりのコメント文をつけて解読してみてください。
    (プログラムは、教科書p.31の2.12から17までの解答例をまとめたもの。若干の変更あり)

main 関数は以下。授業中の例題を実行。[c], [c,v], などと変化する。

print_array関数の表示から、リスト構造を表現している2つの配列の変化を説明しよう。(この実行例は問2.11)

int main(void){
   printf("(initialized)\n");
   initialize();
   print_array(0, MAX-1); /* 初期状態をプリント */

   printf("(insert 1 a)\n");
   insert(next[0],1,'a');
   print_array(0, MAX-1); /* 状態をプリントして確認 */

   access(next[0], 1); /* このaccess関数は、1番目の要素をreturn。ここでは戻り値を表示していない */

   printf("(insert 1 c)\n");
   insert(next[0],1,'c');
   print_array(0, MAX-1);  

   printf("(insert 2 v)\n") ;
   insert(next[0],2,'v');
   print_array(0, MAX-1);  

   printf("(delete 1)\n") ;
   delete(next[0],1);
   print_array(0, MAX-1); 

   printf("(insert 2 a)\n") ;
   insert(next[0],2,'a');
   print_array(0, MAX-1); 

   printf("(delete 3)\n") ;
   delete(next[0],3);
   print_array(0, MAX-1);

/* empty関数使用の例 先頭から、1つずつプリントして削除する。手繰られているイメージ
   while(!empty()) {
      printf("%c",access(next[0],1));
      delete(next[0],1);
   }
   printf("\n");
 */

   return(0);
}



<実行例> 

initialze関数、insert関数、delete関数のプログラムを読んで、これらの実行例が、何をどのように表しているのか、説明しなさい。 

(initialized)
next[0] =   1: data[0] =
next[1] =   0: data[1] =
next[2] =   3: data[2] =
next[3] =   4: data[3] =
next[4] =   5: data[4] =
next[5] =   6: data[5] =
next[6] =   7: data[6] =
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(insert 1 a)
next[0] =   1: data[0] =
next[1] =   3: data[1] =
next[2] =   4: data[2] =
next[3] =   0: data[3] = a
next[4] =   5: data[4] =
next[5] =   6: data[5] =
next[6] =   7: data[6] =
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(insert 1 c)
next[0] =   1: data[0] =
next[1] =   4: data[1] =
next[2] =   5: data[2] =
next[3] =   0: data[3] = a
next[4] =   3: data[4] = c
next[5] =   6: data[5] =
next[6] =   7: data[6] =
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(insert 2 v)
next[0] =   1: data[0] =
next[1] =   4: data[1] =
next[2] =   6: data[2] =
next[3] =   0: data[3] = a
next[4] =   5: data[4] = c
next[5] =   3: data[5] = v
next[6] =   7: data[6] =
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(delete 1)
next[0] =   1: data[0] =
next[1] =   5: data[1] =
next[2] =   6: data[2] =
next[3] =   0: data[3] = a
next[4] =   5: data[4] =
next[5] =   3: data[5] = v
next[6] =   7: data[6] =
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(insert 2 a)
next[0] =   1: data[0] =
next[1] =   5: data[1] =
next[2] =   7: data[2] =
next[3] =   0: data[3] = a
next[4] =   5: data[4] =
next[5] =   6: data[5] = v
next[6] =   3: data[6] = a
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(delete 3)
next[0] =   1: data[0] =
next[1] =   5: data[1] =
next[2] =   7: data[2] =
next[3] =   0: data[3] =
next[4] =   5: data[4] =
next[5] =   6: data[5] = v
next[6] =   0: data[6] = a
next[7] =   8: data[7] =
next[8] =   9: data[8] =
next[9] =   2: data[9] =

(最後の状態は、リスト [v,a] を表現している。どこからどのように読めば、[v,a]なのか。
次にinsert(next[0],3,'c')などとすれば、配列はどのように変わるのか) 

(全く、コメントありません。本来、ここから読むべき)

解答例

#include <stdio.h>
#define MAX 10

/* ノーヒントバージョン */
void print_array(int from, int to);

char access(int p, int i);
int newcell(void);
void insert(int p, int i, char x);
void delete(int p, int i);
void initialize(void);
int empty(void);
int next[MAX];
char data[MAX];


void initialize (void) {
   int i;
   for (i = 0 ; i < MAX; i++) {
      next[i]=i+1;
      data[i]='\0';
   }
   next[1]=0;
   next[MAX-1]=2;
}

char access (int p, int i) {
   if (next[p] != 0) {
      if (i > 1) {
         return (access(next[p],i-1));
      } else {
         return (data[next[p]]);
      }
   } else {
      printf("List L ends before arriving ");
      printf("at the position.\n");
      return('\0');
   }
}

int newcell (void) {
   int new;
   if (next[next[MAX-1]] != MAX-1) {
      new = next[next[MAX-1]];
      delete (next[MAX-1],1);
      return(new);
   }
   printf("List overflows.\n");
   return(MAX);
}

void insert (int p, int i, char x) {
   int q;
   if (p != 0) {
      if (i > 1) {
         insert(next[p],i-1,x);
      } else {
         q = newcell();
         data[q] = x;
         next[q] = next[p];
         next[p] = q;
      }
   } else {
      printf("List L ends before arriving ");
      printf("at the position.\n");
   }
}


void delete (int p, int i) {
   if (next[p] != 0) {
      if(i > 1) {
         delete (next[p],i-1);
      } else {
         data[next[p]]='\0';
         next[p]=next[next[p]];
      }
   } else {
      printf("List L ends before arriving ");
      printf("at the position.\n");
   }
}

int empty (void) {
   if (next[next[0]] == 0) {
      return(1);
   }
      return(0);
}

void print_array(int from, int to) {
   int i;

   for (i = from ; i <= to; i ++)
     printf("next[%d] = %3d: data[%d] = %c \n",i,next[i],i, data[i] );

   printf("\n\n");
}

int main(void){
   printf("(initialized)\n");
   initialize();
   print_array(0, MAX-1); /* 初期状態をプリント */

   printf("(insert 1 a)\n");
   insert(next[0],1,'a');
   print_array(0, MAX-1); /* 状態をプリントして確認 */

   access(next[0], 1); /* このaccess関数は、1番目の要素をreturn。ここでは戻り値 を表示するなどしていない */

   printf("(insert 1 c)\n");
   insert(next[0],1,'c');
   print_array(0, MAX-1); /* 初期状態をプリント */

   printf("(insert 2 v)\n") ;
   insert(next[0],2,'v');
   print_array(0, MAX-1); /* 初期状態をプリント */

   printf("(delete 1)\n") ;
   delete(next[0],1);
   print_array(0, MAX-1); /* 初期状態をプリント */

   printf("(insert 2 a)\n") ;
   insert(next[0],2,'a');
   print_array(0, MAX-1); /* 初期状態をプリント */

   printf("(delete 3)\n") ;
   delete(next[0],3);
   print_array(0, MAX-1); /* 初期状態をプリント */

/* empty関数使用の例 先頭から、1つずつプリントして削除する。手繰られているイメ ージ
   while(!empty()) {
      printf("%c",access(next[0],1));
      delete(next[0],1);
   }
   printf("\n");
*/

    return(0);
}