配列の中に、リストが入っているものをボトムアップ形式でマージソートしています

このQ&Aのポイント
  • 配列の中に、リストが入っているものをボトムアップ形式でマージソートしています。
  • リストをマージする際に、配列の要素数とノードの次に文字列が入ったノードの関係に問題があります。
  • printf関数が実行できないため、マージしたリストや配列の要素の状態がわかりません。
回答を見る
  • ベストアンサー

配列の中に、リストが入っているものをボトムアップ形式でマージソートして

配列の中に、リストが入っているものをボトムアップ形式でマージソートしています。 リストは、空のノードの次に文字列が入ったノード、というものです。 sizeは、配列の要素数となっています。 merge_listは、リスト2つをマージするものです。 2つのリストをマージして、ひとつになったリストを最初のリストが入っていた配列に入れる。 もう片方はNULLにする。 順に繰り返していき、配列の要素が1つのみになったらそれを返す・・・ といったアルゴリズムなのですが、うまく配列の中のリストが指定できません。 調べたところ、おそらくプログラム中の矢印があるところに問題があってprintfが実行できないようなんですが、原因がわかりません。 同じ原因によりmerge_listに、マージしたいリストが入っていないようなんですが・・・。 説明下手ですいませんが、どうかよろしくお願いします。 typedef struct list * word_list; struct list { char* word; word_list rest; }; word_list _mergesort(word_list* word_lists, int size) { int i=0, j; while(1){ while(1){ while(word_lists[i] =NULL) //配列に一つ目の要素が見つかるまで回す <- 原因 i++; j = i+1; while(word_lists[j] =NULL) //配列に二つ目の要素が見つかるまで回す<- 原因   j++;       if(j == size) //マージする要素が後ろになかったら終了  break; //printf("%d,%d\n",i, j); printf("%s\n",word_lists[i] ->rest ->word);  <-ここでエラー printf("%s\n",word_lists[j] ->rest ->word); word_lists[i] =merge_list(word_lists[i], word_lists[j]); word_lists[j] =NULL; printf("%s",word_lists[i]->rest ->word); i = j+1; } if(i !=0){ i = 0; }else{ break;    //要素がひとつしかなかったら終了 } } return word_lists[0]; }

  • bh_wy
  • お礼率50% (1/2)

質問者が選んだベストアンサー

  • ベストアンサー
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.2

> while(word_lists[j] =NULL) while (j < size && word_lists[j] == NULL) i の方も同様。にしても while (1) が既に二重なのが気になる。 > if(j == size) if(j >= size) の方が安全な気がする。

bh_wy
質問者

お礼

ありがとうございます! 解決しました・・・!

その他の回答 (1)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

とりあえず、回答しようとする側でコンパイル~実行ができるよう、 ソースコード全体を載せてみてください。 >char* word; 何となくですけど、ポインターでいいのかな?配列でなくていいのかな? という気がしています。 まあ、ソースコード全体を見てからの話ですね。

bh_wy
質問者

補足

回答ありがとうございます。 指定されているため、構造体は変更できないんです・・・。 #include<stdio.h> #include<stdlib.h> #include<string.h> #define WORDS_NUM 10 /* 単語リスト型 word_list の定義 (変更しないこと) */ typedef struct list * word_list; struct list { char* word; word_list rest; }; char *words[10] = {"cat", "dog", "tiger", "bug", "bird", "fish", "cat", "cow", "pig", "rat" }; word_list make_clist(char *data) { int i =0; word_list head, n; head = (word_list)malloc(sizeof(struct list)); head->rest = NULL; n = (word_list)malloc(sizeof(struct list)); //ノードの容量を作る n->word = data; n->rest = head->rest; head->rest = n; return head; } word_list merge_list(word_list x, word_list y){ word_list p, p_head; x = x ->rest; y = y-> rest; p = (word_list)malloc(sizeof(struct list)); p ->rest = NULL; p_head = p; while( x != NULL && y != NULL ) { if(compare(x->word,y->word) == -1) { p->rest = x; p = x; x = x->rest; }else{ p->rest = y; p = y; y = y->rest; } } if( x == NULL ) { p->rest = y; }else{ p->rest = x; } return p_head; } /* 文字列比較の関数*/ int compare(char* w1,char* w2) { int len1 = strlen(w1), len2 = strlen(w2); if (strcmp(w1, w2) == 0) return 0; while(w1[len1] == w2[len2]){ len1--; len2--; } if(w1[len1] > w2[len2]){ return 1; }else{ return -1; } } int main() { int i; word_list w, word_lists[WORDS_NUM]; int n = 10 for(i =0; i<n; i++){ word_lists[i]=make_clist(words[i]); } w = _mergesort(word_lists, n); for(i=0; i < n; i++){ w = w->rest; printf("%s\n", w->word); } }

関連するQ&A

  • マージソートのプログラム

    ↓が自分の作ったマージソートのプログラムなのですが、コンパイルするとエラーが起きてしまいます。 mergesort()にポインタを引数として渡してる、引数の数が足りない、ということが書いてありますが…。 ちゃんとint型を渡してるし、引数の数も合ってるように思います。 どこがおかしいのでしょう? #include<stdio.h> #include<stdlib.h> #include<time.h> #define Max 255 int A[Max]; main(){ int n,k; n=inputdata(); int w=1; mergesort(w,n); printdata(n); return(0); } inputdata(){ //配列に乱数を要素として入れていく int n,i; printf("n= "); scanf("%d",&n); //使用者にいくつの要素を入れるか指定してもらう srand(time(NULL)); for(i=1; i<=n; i++){ A[i]=1+rand()%30; } printf("A[%d]={%d,",n,A[1]); for(i=2;i<n;i++) printf("%d,",A[i]); printf("%d}\n",A[n]); return(n); } void mergesort(int p, int r){ int q; if(p<r){ q=(p+r)/2; mergesort(p,q); mergesort(q+1,r); merge(p,q,r); } } void merge(int p, int q, int r){ int i,j,k,B[Max]; i=p; j=q+1; for(k=p;k<=r;k++){ if((j>r) || ((i<=q)&&(A[i]<=A[j]))){ B[k]=A[i]; i++; }else{ B[k]=A[j]; j++; } } for(k=p; k<=r; k++) A[k]=B[k]; } printdata(int n){ int i; printf("A[%d]={%d,",n,A[1]); for(i=2; i<n; i++) printf("%d,",A[i]); printf("%d}\n",A[n]); } ・エラーメッセージ merge1.c: In function ‘main’: merge1.c:12: warning: passing argument 1 of ‘mergesort’ makes pointer from integer without a cast merge1.c:12: error: too few arguments to function ‘mergesort’ merge1.c: At top level: merge1.c:31: error: conflicting types for ‘mergesort’ /usr/include/stdlib.h:294: error: previous declaration of ‘mergesort’ was here merge1.c:41: warning: conflicting types for ‘merge’ merge1.c:37: warning: previous implicit declaration of ‘merge’ was here

  • マージソートについて

    マージソートの要素の比較と交換回数を計測するプログラムを作っているのですが、マージのどの段階が交換処理になるのかが分からず困っています。 マージ処理の実行回数をカウントする配列sを設けて処理をカウントする場合、以下のプログラムだとどのタイミングでカウントすればよいでしょうか? ちなみに配列aは初めに値を割り振った配列で、配列bは別途で用意した作業用配列です。 最後のfor文やif文付近で配列の値を変化させて計測してみたのですが、計算量に合った動きをしてくれませんorz void merge_sort(int a[], int low, int high){ int mid, i, j, k; if(low >= high) return; mid = (low + high)/2; merge_sort(a, low, mid); merge_sort(a, mid+1, high); for(i = low; i <= mid; i++) b[i] = a[i]; for(i = mid+1, j=high; i <= high; i++, j--) b[i] = a[j]; i = low; j = high; for(k = low; k <= high; k++){ if(b[i] <= b[j]){ a[k] = b [i++]; } else{ a[k] = b[j--]; } } }

  • マージソート

    マージソートの実行時間を測定するプログラムを書いています。 コンパイルの時にはエラーが出ないのですが、実行するとコマンドプロンプトが強制終了されます。 どこが悪いか、どう直せばいいのか指摘していただけないでしょうか? よろしくお願いします。 ~qtime.c~ //マージソート実行用プログラム //bcc32 mtime.c merge.c m1.c sfmt.c #include <stdio.h> #include <stdlib.h> #include <time.h> #include "sfmt.h" #define MAX 5000 void merge_sort(int a[], int start, int end); main() { int i , x[MAX] , n; time_t start , end ; int sn; printf("適当な数字の入力 : "); scanf("%d", sn); init_gen_rand(sn); for(i=0; i<MAX; i++) x[i]= (gen_rand32()% MAX);; n=MAX; start = clock(); //測定対象プログラム merge_sort(x, 0, n-1); end = clock(); printf("sort\n"); for(i =0 ; i < n ; i++ ) if ( i == i/100*100) printf("%d\n" , x[i]); printf ("実行時間: %f sec\n" , (double)(end-start) /CLOCKS_PER_SEC); return 0; } ~merge.c~ int b[100]; void merge_array(int x[], int start, int end) { int mid, i, j, k; mid = (start + end) /2; i = start; j = mid + 1; for(k = start; k <= end; k++){ if(x[i] > x[j] && j <= end || i > mid){ b[k] = x[j]; j++; } else{ b[k] = x[i]; i++; } } for(k = start; k <= end; k++){ x[k] = b[k]; } } ~m1.c~ void merge_array(int x[], int start, int end); void merge_sort(int a[], int start, int end); void merge_sort(int a[], int start, int end) { int mid; if(start >= end) return; mid = (start + end) / 2; merge_sort(a, start, mid); merge_sort(a, mid + 1, end); merge_array(a, start, end); }

  • マージソートについて。

    マージソートについて勉強しており、プログラムを作ってみたのですが どうしてもcc=~~の箇所の数値がおかしく表示されてしまいます #include<stdio.h> int main(void) { int a[5]={20,40,15,35,50}; int b[3]={55,20,65}; int c[8]; int i,z,k; printf("a="); for(i=0;i<5;i++) { printf("%d ",a[i]); } printf("\nb="); for(z=0;z<3;z++) { printf("%d ",b[z]); } while(i <= 5 && z <= 3){ if(i < z){ a[i]=c[k]; i++; } else if(i > z){ b[z]=c[k]; z++; } } while(i<5 && z<3) { i=k; i++; z=k; z++; } printf("\nc=") ; for(k=0;k<8;k++) { printf("%d ",c[k]); } return 0; } ご教授していただければ幸いです。

  • 非再帰のマージソートについて

    非再帰のマージソートを作成しているのですが、 上手いこと出来なくて困っています。 条件として配列の開始と終了のインデックスを指定して、 その間の要素だけをソートしたいのです。 ex:  int array[10] = { 9,8,7,6,5,4,3,2,1,0 };  MergeSort( array, 2, 6 ); // array[2]~array[6]をソート  for( int i=0; i<10; i++ ) printf( "%d, ", array[i] );  出力)   9, 8, 3, 4, 5, 6, 7, 2, 1, 0, 以下のサイトで公開されているマージソートを元に 私なりに弄ってはいるのですが、 メモリを壊してしまうようなエラーが頻発して、 どうもうまくいかないのです・・・。 http://besky-works.spaces.live.com/Blog/cns!555CF2E2F9E31C71!557.entry どなたがおわかりの方がいらっしゃれば、 その方法を教えていただければ助かります。

  • リスト内の値を分割して、2つの配列に入れるには

    初歩的な質問になるかと思いますが、 どうかご指導願います。 リストにはHashMap用のkeyとvalueが lists.add("key1"); lists.add("value1"); lists.add("key2"); lists.add("value2"); lists.add("key3"); lists.add("value3"); ↑のような感じでセットされています。 このリストの要素をキーと値を別々の配列にセットしたいのですが、 どうすればいいのかわかりません。 配列 key         配列 value String key[]          String value[] key[0] = "key1";       value[0] = "value1";  key[1] = "key2";       value[1] = "value2";   key[2] = "key3";       value[1] = "value3"; ↑のような感じにfor文やwhileを使ってできると思うのですが、 ど素人のため全くうまくいきません。 。ご指摘ご指南頂きたく思います。

    • ベストアンサー
    • Java
  • 単行リストのソートのプログラムについて

    単行リストのソースでわからなくなったので質問させていただきます。 #include<stdio.h> //---------------------------------------------------------- // InitBanpei // 番兵の初期化 //---------------------------------------------------------- // input: struct pNode* pNode //番兵のアドレス //---------------------------------------------------------- void InitBanpei(struct node* pStartNode,struct node* pEndNode); //---------------------------------------------------------- // IsBanpei // 番兵チェック //---------------------------------------------------------- // input: struct pNode* pNode //番兵のアドレス // out : true //成功 // false //失敗 //---------------------------------------------------------- int IsBanpei(struct node* pNode); //構造体 struct node { char name[30]; int kokugo; int suugaku; int eigo; int goukei; struct node* pNext; }; int main(void) { FILE* fp; struct node useStart,useEnd; struct node *p,*j,*max,*a; int stich=0; char work[256]; InitBanpei(&useStart,&useEnd); IsBanpei(&useStart); IsBanpei(&useEnd); fp=fopen("data.txt","r"); if(fp==NULL) { printf("ファイルを開けません\n"); return 0; } while(feof(fp)==0) { fgets(work,256,fp); stich++; } stich--; printf("%d\n",stich); if(stich==0) { printf("件数は0です\n"); return 0; } fclose(fp); fp=fopen("data.txt","r"); if(fp==NULL) { printf("ファイルを開けません\n"); return 0; } j=NULL; for(int i=0;i<stich;i++) { a=new struct node; if(a==NULL) { printf("メモリが確保できません\n"); return 0; } fscanf(fp,"%s %d %d %d ",&(a->name),&(a->kokugo),&(a->suugaku),&(a->eigo)); a->goukei=a->kokugo+a->suugaku+a->eigo; a->pNext=j; j=a; } useStart.pNext=j; max=&useStart; p=max->pNext; while(max->pNext!=NULL) { j=p; while(j->pNext!=NULL) { if(max->goukei< j->goukei) { max=j->pNext; p=j; } j=j->pNext; } p->pNext=max->pNext; max->pNext=useStart.pNext; max=max->pNext; } a=useStart.pNext; while(a->pNext!=NULL) { printf("%7s %03d %3d %3d %3d点\n ",a->name, a->kokugo,a->suugaku, a->eigo,a->goukei); a=a->pNext; } } //---------------------------------------------------------- // InitBanpei // 番兵の初期化 //---------------------------------------------------------- // input: struct pNode* pNode //番兵のアドレス //---------------------------- //------------------------------ void InitBanpei(struct node* pStartNode,struct node* pEndNode) { pStartNode->pNext=pEndNode; pEndNode->pNext=NULL; } //---------------------------------------------------------- // IsBanpei // 番兵チェック //---------------------------------------------------------- // input: struct pNode* pNode //番兵のアドレス // out : true //成功 // false //失敗 //---------------------------------------------------------- int IsBanpei(struct node* pNode) { if( pNode->pNext!=NULL) { return -1; } return 0; } のソースなのですが、単行リストを使って大きい順に並び替えをしたいのですがうまくできません。どこを直せばいいのでしょうか?分かる方いらしたらソースを書いてくださると助かります。

  • C言語のアルゴリズム、マージソートについて質問です。

    C言語のアルゴリズム、マージソートについて質問です。 例えば下のプログラム #include <stdio.h> void merge(int first, int last, int *data, int *work); int main(void) { int data[9] = {1,8,3,6,5,4,7,2}; int work[9]; int i; merge(0,8,data,work); for(i = 0;i < 9;i++) printf("%d",data[i]); return 0; } void merge(int first, int last, int *data, int *work) { int middle, mae, ato, i; if (first == last) { return; } middle = (first + last) / 2; merge(first, middle, data, work); merge(middle + 1, last, data, work); i = first; mae = first; ato = middle + 1; while (mae <= middle && ato <= last) { if (data[mae] <= data[ato]) { work[i] = data[mae]; i++; mae++; } else { work[i] = data[ato]; i++; ato++; } } while (mae <= middle) { work[i] = data[mae]; i++; mae++; } while (ato <= last) { work[i] = data[ato]; i++; ato++; } for (i = first; i <= last; i++) { data[i] = work[i]; } } まずfirst=0,last=8でmerge関数に入り関数内8行目でmiddle=4となり、 10行目でfirst=0,last=4でmergeに入り同じく8行目でmiddle=2となり、 同じく10行目でfirst=0,last=2でmergeに入り同じく8行目でmiddle=1となり、 同じく10行目でfirst=0,last=1でmergeに入り同じく8行目でmiddle=0となり、 同じく10行目でfirst=0,last=0でmergeに入り3行目のifでreturnします。 そして前回のfirst=0,last=1,middle=0のmerge10行目に戻り, 12行目でfirst=1,last=1でmergeに入り3行目のifでreturnし、 12行目以下の作業をします。 そのまま一番下までいったあとはどうなるのでしょうか? また上で書いた手順もあっている自信はあまりないので ご指摘お願いします。

  • 双方向リストのバブルソートについて

    双方向リストをバブルソートを用いてソートしたいです。 下記がプログラム(一部)ですが、ソートした後にリスト表示すると 無限ループに陥ります。 どこがいけないのでしょうか。 #include <stdio.h> #include <stdlib.h> struct cell{ int data; struct cell *next, *prev; }; void insert_head(struct cell **head, int num){ struct cell *p, *p1; p = *head; p1 = make_cell(); *head = p1; p1->data = num; p1->next = p; if(p1->next != (struct cell *)NULL){ p1->next = p; p->prev = p1; } } void print_list(struct cell *head){ struct cell *p; p = head; printf("data = \n"); while(p != (struct cell *)NULL){ printf("%d\n", p->data); p = p->next; } } void sort_list(struct cell **head){ struct cell *p, *p2; int i, n; n = 0; p = *head; while(p->next != (struct cell *)NULL){ p = p->next; n++; } for(i = 0, p = *head; i < n-2; i++){ if(p->data > p->next->data){ if(p == *head){ *head = p->next; }else{ p->prev->next = p->next; } p2 = p->next; p->next = p->next->next; p->next->next = p; p->next->next->prev = p; p->next->prev = p->prev; p->prev = p2; }else p = p->next; } } int main(void){ struct cell *head = (struct cell *)NULL; int n; while(1){ printf("1:Insert head 2:Insert tail 3:Delete 4:List 5:Sort 6:Exit\n"); scanf("%d", &n); switch(n){ case 1: printf("num = "); scanf("%d", &n); insert_head(&head, n); break; case 2: printf("num = "); scanf("%d", &n); insert_tail(&head, n); break; case 3: printf("num = "); scanf("%d", &n); delete_cell(&head, n); break; case 4: print_list(head); break; case 5: sort_list(&head); break; case 6: return 0; break; } } }

  • 配列の特定の位置から別の配列をマージする方法

    テトリスを作成しています。listという配列の3番目(インデックスの)を始点として、minoという配列をマージしたいです。このような場合の記述方法がわかりません。 以下がコードですが、どうやって始点を指定するのでしょうか。 list[3]を始点とします。 var list = [1,0,0,0,0,0,0,1] var mino = [2,2] func _ready(): #3番目からスタート for i in range(mino.size()): list[i] = mino[i] print(list) 得たい結果はこうです。ヒントだけでも貰えればと思います。 [1,0,0,2,2,0,0,1]