• 締切済み

構造体配列のクイックソート

こんにちわ。 構造体配列のリストを ポインタのつなぎ変えによるクイックソートで 以下のようなソートをしたいのですが、悩んでおります。 struct info { int count; struct info *prev; struct info *next; }; int main () { struct info info[5]; /* 初期値設定 */ quick_sort(info, 0, 5); return 0; } 上記のようにして、クイックソートをしたいのですが、 よくあるクイックソートだと 例えば初期値を <配列のindex>要素の値を <0> <1> <2> <3> <4> 5 1 4 3 2 などと定義した場合 普通のクイックソートだと <0> <1> <2> <3> <4> 1 2 3 4 5 というように並び変えられてしまい <配列のindex>と 要素の値の組み合わせが変わってしまいますが、 この組み合わせを変えず、 struct info *if; if = info; for (i=0; i<MAX; i++){ printf("%d", if->count); if = if->next; } printf("\n"); とすることで、indexとしては昇順になっていないが *nextをたどっていくことでちゃんと目的の値の昇順になっている というのを実現したいのですが、ポインタのつなぎ変えか何かが 間違っているようで うまいことできていません。 どなたかご教授いただけますでしょうか。 申し訳ありませんが、よろしウお願いいたします。

みんなの回答

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.7

一般論です。平均オーダーはクイックソート、マージソートともO(n*log(n))で同等ですが、係数はクイックソートの方が小さく、一般に倍ほど速いといいます。ただ最悪時はクイックソートがO(n^2)と悪化するのに対してマージソートは最悪でもO(n*log(n))で安心できます。 またクイックソートは評価値が同じ項目の順序が安定しない性質があるので、複数の評価値で順にソートする場合には向きません。 こういった特徴もあり、Javaのライブラリなどでは、基本型はクイックソート、オブジェクト型はマージソートをベースとするアルゴリズムを使っています。リンクリストならマージソートの方がお勧めできるかと思います。

回答No.6

#include <stdio.h> #include <stdlib.h> #include <time.h> typedef struct list{ int no; char name[8]; struct list *next; } list; void printlist(list *head) { while(head){ printf("(%d %s)", head->no, head->name); head = head->next; } putchar('\n'); } void printarray(const list *l, int n) { int i; for(i = 0; i < n; ++ i) printf("(%d %s)", l[i].no, l[i].name); putchar('\n'); } list *q_Sort(list *head) { if(head && head->next){ list *l = NULL, *m, *r = NULL, *k, *p; m = k = head; head = head->next; k->next = NULL; /* 念のため */ while(head){ p = head; head = head->next; if(p->no < k->no) p->next = l, l = p; else if(p->no == k->no) p->next = m, m = p; else p->next = r, r = p; } if(head = q_Sort(l)){ for(p = head; p->next; p = p->next) ; p->next = m; } else head = m; k->next = q_Sort(r); } return head; } int main(void) { list l[] = {{0, "a"}, {0, "b"}, {0, "c"}, {0, "d"}, {0, "e"}, {0, "f"}, {0, "g"}, {0, "h"}, {0, "i"}, {0, "j", NULL}}; list *head; const int n = sizeof l / sizeof l[0]; int i; srand((unsigned)time(NULL)); for(i = 0; i < n - 1; ++ i) l[i].no = rand() % 10, l[i].next = l + i + 1; l[i].no = rand() % 10; head = q_Sort(l); printlist(head); printarray(l, n); return 0; }

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

クイックソートは本質的にシーケンシャルアクセスしか使わないので, 双方向リストに適用することも (一応は) 可能ですよ>#3. ただ「同じ値もかなり含まれると思う」というのはちょっと不安. ピボットとして「先頭と中間と末尾の値の平均」を使ってるけど, 「ソートしようとしている部分」がすべて同じ値だった場合, 当然これらはすべて同じ値であり, したがってピボットの値も同じになります. ところが, そのような場合クイックソートの性能は最悪になる可能性があります. 「どんなデータが来てもそれなりに効率的に実行できる」という意味ではマージソートの方が安心できるかなぁ.

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

> あ、また、どうしても qsortなどの既存関数は使えず、全て自分で qsort() は説明で出しただけで、実際は御自分の実装に置き換えることを想定しています。 > 中身全体を変えるのではなく、順番構成となるポインタ値だけを変更して info[] の中身自体は操作していません。 for (i = 0; i < 5; i++) printf("%d:%d ", i, info[i].count); なので、もとの順が欲しければ info[] でアクセス、ソート済が欲しければ ap[] 経由、next,prev を使いたければ、ap[] 経由で設定してやれば、もう ap は free() してかまいません。割とよくやる手順だと思いますが。

  • tossy2011
  • ベストアンサー率17% (3/17)
回答No.3

双方向リストの場合配列の添え字でアクセスできないので 基本的にクイックソートはあんまり使わないと思います。 マージソートでは駄目なのでしょうか?

donntakosu
質問者

補足

ご回答 ありがとうございますm(_ _)m 実際には、かなり大量なデータをソートしなければならなくなるのですが、また、同じ値もかなり含まれると思うのですが、この場合、効率的には クイックソートとマージソート どちらのほうがよいのでしょうか? もともとクイックソートを選んだのは あまり知識がなかったためでもあり、効率的に変わらず、下記に示しましたことが実現できるのであればマージソートにしたいと思います。これからまた勉強しなければなりませんが(^^; あの、ちなみに、この一番の問題となっております、構造体配列のindexと、 構造体内の変数の値の組み合わせは変えたくなく、構造体内のprev, next変数の値の変更によるポインタの繋ぎ変えだけで ソートを実現したいのですが、 そのための注意事項や 実現の仕方について 少し具体的にアドバイスいただくことはできますでしょうか(>_<) もしトンチンカンなことを言っていたらすみません;

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

どうしてもポインタのリンクでやりたいのでしたら、無視してくれてかまいませんが、単に間接参照したのではダメなのですか? こんな感じ。なんかあれば補足してください typedef struct info { int count; struct info *prev; struct info *next; } * info_t; int icmp(void const *a, void const *b) { info_t const *a1 = a; info_t const *b1 = b; return (*a1)->count - (*b1)->count; } struct info info[] = {{5}, {1}, {4}, {3}, {2}}; int main(int argc, char *argv[]) { int i; info_t ap[5]; for (i = 0; i < 5; i++) ap[i] = info + i; qsort(ap, 5, sizeof(ap[0]), icmp); printf("info[]: "); for (i = 0; i < 5; i++) printf("%d:%d ", i, info[i].count); printf("\n *ap[]: "); for (i = 0; i < 5; i++) printf("%d:%d ", i, ap[i]->count); printf("\n"); return 0; }

donntakosu
質問者

補足

さっそくの回答 ありがとうございますm(_ _)m 実は 都合上 どうしても 配列のindexと、中身の値の組み合わせは 変えたくないのです(>_<) その場合は、ポインタの繋ぎ変えを行うしかないかと思ってまして。 例えば array[0] = { (int count=)5, (*prev=)Aprev, (*next=)Anext } array[5] = { (int count=)2, (*prev=)Bprev, (*next=)Bnext } だとして、このふたつのリスト中での位置を逆転させたいとしたら array[0] = { (int count=)5, (*prev=)Bprev, (*next=)Bnext } array[5] = { (int count=)2, (*prev=)Aprev, (*next=)Anext } というような感じにしたいのです(>_<) つまり、普通に中身だけ交換していくクイックソートのアルゴリズムのやつを 中身全体を変えるのではなく、順番構成となるポインタ値だけを変更して ソートを行いたく、つまり、ソート後に for (i = 0; i < 5; i++) printf("%d:%d ", i, ap[i]->count); というような表示を行った場合は、依然 5 1 4 3 2 と表示され ap = ap->next; とした時に 目的の値の昇順に表示される というようなものを 目指しているのですが、そのような場合 ポインタの繋ぎ変え方や 再帰呼び出しのところでの引数にとまどっております(>_<) あ、また、どうしても qsortなどの既存関数は使えず、全て自分で 書かなければならないのです(>_<) なんだか注文が多くてすみません(>_<)

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

>ポインタのつなぎ変えによるクイックソート っていうのが今ひとつうまくイメージできませんが、 何はともあれ、ソースコード全体を見せてください。 そうすれば、何かが見えてくるかもしれません。

donntakosu
質問者

お礼

あ、すみません、pだのheadだのは さきほど奮闘中に このようにポインタの繋ぎ変え?でソートを行う場合 headを用意していないと 先頭がどこか分からなくなる というような記述をネットで目にしまして 試行錯誤中のため書いてしましましたが、 p = &head; p->next_nb_info = left0; p = left0; は 無視していただいてかまいません;; 必要であれば、そのようにコメントしていただいてもかまいません;;

donntakosu
質問者

補足

こちらも さっそくの回答 ありがとうございますm(_ _)m #include <stdio.h> #define MAX_IDX 6 struct nb_info { int ec; struct nb_info *prev_nb_info; struct nb_info *next_nb_info; }; int j = 0; void quick_sort(struct nb_info *left_nb_info, struct nb_info *right_nb_info, int i_left, int i_right) { int left = i_left; int right = i_right; struct nb_info *left0; struct nb_info *right0; struct nb_info *nb_left, *nb_center, *nb_right; struct nb_info head, *p; int pivot; int i; left0 = left_nb_info; right0 = right_nb_info; p = &head; p->next_nb_info = left0; p = left0; nb_left = left_nb_info; nb_right = right_nb_info; nb_center = nb_left; for (i = 0; i < (right-left)/2; i++) nb_center = nb_center->next_nb_info; if (left >= right) return; pivot = (nb_left->ec + nb_center->ec + nb_right->ec)/3; while (1) { struct nb_info tmp; struct nb_info *tmp_prev; struct nb_info *tmp_next; while (nb_left->ec < pivot) { left++; nb_left = nb_left->next_nb_info; if (nb_left == NULL) break; } while (nb_right->ec > pivot) { right--; nb_right = nb_right->prev_nb_info; if (nb_right == NULL) break; } if (left >= right) break; tmp = *nb_left; *nb_left = *nb_right; *nb_right = tmp; tmp_prev = nb_left->prev_nb_info; tmp_next = nb_left->next_nb_info; nb_left->prev_nb_info = nb_right->prev_nb_info; nb_left->next_nb_info = nb_right->next_nb_info; nb_right->prev_nb_info = tmp_prev; nb_right->next_nb_info = tmp_next; left++; nb_left = nb_left->next_nb_info; right--; nb_right = nb_right->prev_nb_info; } if (i_left < left-1) quick_sort(left0, nb_left->prev_nb_info, i_left, left-1); if (right+1 < i_right) quick_sort(nb_right->next_nb_info, right0, right+1, i_right); } int main(){ struct nb_info nb_info[MAX_IDX]; struct nb_info *nb; int i; /* 配列の初期化 */ quick_sort(&nb_info[0], &nb_info[5], 0, MAX_IDX-1); } 字数制限のため main()関数内の 結果表示部は省きました。 これで 私の頭の中はイメージできますでしょうか 汗 いろいろ間違えているのでしょうね;;

関連するQ&A

  • クイックソートについて

    下記のソースプログラムのquick_sort_coreの部分がわかりません。 わかる方助けてください。 あとこのソースを降順にした場合の変更点も教えていただけると助かります。 #include <stdio.h> /* printf()利用のため */ #include <stdlib.h> /* rand()利用のため */ #include <time.h> /* clock()利用のため */ #define N 10 /* 整列対象要素数 */ /** * 配列の中身を表示する関数 * @param a 表示する配列 * @param n 配列の要素数 */ void print_array(const int a[], int n) { int i; for (i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); } /** * 整列されているかどうか確認する関数 * @param a 確認対象配列 * @param n 配列の要素数 */ void is_sorted(const int a[], int n) { int i; for (i = 0; i < n - 1; i++) { if (a[i] > a[i + 1]) { printf("昇順に整列されていません\n"); return; } } printf("昇順に整列されています\n"); } /** * クイックソートの本体 * @param a 整列対象配列 * @param l 対象の最初の要素番号 * @param r 対象の最後の要素番号 */ void quick_sort_core(int a[], int l, int r) { /* ここを実装する */ } /** * これまでの整列関数のインターフェースにあわせるクイックソート呼び出し関数 * @param a 整列対象配列 * @param n 配列の要素数 */ void quick_sort(int a[], int n) { quick_sort_core(a, 0, n - 1); } int main(void) { int i; int n = N; /* 整列対象要素数 */ int a[N]; clock_t start,end; /* 0からRAND_MAXの一様乱数をn個生成し、配列aに格納 */ for (i = 0; i < n; i++) { a[i] = rand(); /* 出力確認(print_array)するときは a[i]=rand()%100 としておくと見やすい */ } /* 昇順にソートされているか確認(デバッグ用) */ is_sorted(a, n); /* 配列の中身を確認(デバッグ用) */ print_array(a, n); /* 開始時刻の取得 */ start = clock(); /* クイックソート関数の呼び出し */ quick_sort(a, n); /* 終了時刻の取得 */ end = clock(); /* 配列の中身を確認(デバッグ用) */ print_array(a, n); /* 昇順にソートされているか確認(デバッグ用) */ is_sorted(a, n); /* 実行時間の表示 */ printf("%d 個の要素のクイックソートの実行に %f [秒]かかりました\n", n, (double)(end - start) / CLOCKS_PER_SEC); return 0; }

  • 構造体のリストをソートしたい。

    ある名簿のリストを作りました。 以下のような構造体で、 typedef struct meibo{ char name[10]; int old; struct meibo *next; }MEIBO; これを、ポインタp->next->nameをたどっていって、名前が辞書順になるようにリストを作ったのですが、 これを年齢順にソートして表示させたいんです。 どんな方法があるんでしょうか? 一旦すべてを配列に格納して、クイックソート…とかも考えたのですが、すごく領域をとるし、なんか2度手間(最初から配列に順に格納していけばよかったなぁ・・・と。 それでもやっぱり最初から名列順にするときから配列に入れておくほうがいいのでしょうか? 教えてください。 (最初から年齢を比較してリストを作れば・・ってのはなしで、名列順のリストが存在するものとしてください。)

  • クイックソートの比較交換回数について

    クイックソートの比較交換回数を変数countで計算し、表示させようとしているのですがうまくいきません。 改善策を教えていただけないでしょうか。 /* クイックソート */ void quickSort(randomlist_t data[],int n){ /* 実質的な処理は何もせず、クイックソートを実際に行う関数を呼び出すのみ */ int count = 0; quickSort_1(data,0,n-1,count); printf("count:%d\n",count); } /* 実際にクイックソートを行う関数 */ void quickSort_1(randomlist_t data[],int l,int r,int count){ int v; if(l >= r) /* 整列する要素が1つなら、何もしないでリターンする */ return; v = partition(data,l,r,count); /* 枢軸vを基準に分割する */ quickSort_1(data,l,v-1,count); /* 左の部分の配列a[l]~a[v-1]を整列する */ quickSort_1(data,v+1,r,count); /* 右の部分の配列a[v+1]~a[r]を整列する */ } /* 配列a[l]~a[r]を分割する。枢軸の添え字を返す */ int partition(randomlist_t data[],int l,int r,int count){ int i,j,pivot; randomlist_t t; i = l - 1; j = r; /* ポインタiとjを初期化する */ pivot = data[r].no; /* 一番右端の要素を枢軸にする */ for(;;){ /* ポインタiとjとがぶつかるまで繰り返す */ while(data[++i].no < pivot) count++; /* ポインタiを右へ進める */ while(i < --j && pivot < data[j].no) count++; /* ポインタjを左へ進める */ if(i >= j) break; /* ポインタiとjがぶつかったらループを抜ける */ t = data[i]; data[i] = data[j], data[j] = t; /* iの指す要素とjの指す要素を交換する */ count++; } t = data[i]; data[i] = data[r]; data[r] = t; /* a[i]と枢軸を交換する */ count++; return i; }

  • クイックソートがうまくいかない

    クイックソートとはこういう仕様のソートのことです。 (1)バラバラの配列から基準値を設定する。 (2)前から順番に辿って行って基準値よりも大きいならば、基準値よりも後に移動、小さいならば、基準値よりも前に移動させる。(私のプログラムの場合は基準値を配列の一番目の数に設定しています。) (3)小さいほうと大きいほうの二つのグループに分かれたらまたそれらのグループごとにクイックソートにかける。 (4)二つのグループを分けることができなくなればソート完了。 自分で確かめてみたのですが、どうやら関数QuickSortの中でさらに再帰的にQuickSortにかけるときにバグが発生しているようです。ですが、なぜバグが起きるのかわかりません。 お手数ですが、よろしくお願いいたします。 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define N 10 void QuickSort(char mi,char *hai,int youso) { char *shoubox; char *bigbox; int k=0; int q=0; int i,len,len2; /*もし配列haiの大きさが1ならば終了*/ if(strlen(hai)==1) { return; } /*配列の2番目から最後まで基準値からの大小により仕分けしていく。大きいならば、配列bigboxに小さい*/ /*ならば配列shouboxにそれぞれ入れる。*/ for(i=1;i<youso-1;i++) { if(hai[i]>mi) { bigbox[k++]=hai[i]; } else { shoubox[q++]=hai[i]; } } /*仕分け処理はここまで*/ /*小さいほうの配列と大きいほうの配列をそれぞれクイックソートにかける再帰処理。*/ QuickSort(shoubox[0],shoubox,q); QuickSort(bigbox[0],bigbox,k); /*それぞれのソートが完了したら、配列haiに「小さいほうの配列」→「基準値」→「大きいほうの配列」 の順に値を代入していく。*/ len=strlen(shoubox); for(i=0;i<len;i++) { hai[i]=shoubox[i]; } hai[len]=mi; len2=strlen(bigbox); for(i=(len+1);i<len+len2;i++) { hai[i]=bigbox[i]; } /*代入処理ここまで。*/ } int main(void) { char array[N]; char m; int i,val,j; srand(time(NULL)); /*(1~10)までの数字をランダムに入力する処理*/ for(i=0;i<N;i++) { do{ val=rand()%10; for(j=0;j<i;j++) { if(val+'0'==array[j]) { break; } } }while(j<i); array[i]=val+'0'; } /*ランダムに値を入力する処理ここまで*/ m=array[0]; /*値配列の最初を基準値mに設定*/ QuickSort(m,array,N); /*基準値、配列、要素数を実引数として、クイックソートを呼び出す。*/ /*昇順に並べ替えた配列arrayを出力する。*/ for(i=0;i<N;i++) { printf("array[%d]=%c\n",i,array[i]); } return 0; }

  • クイックソートについて

    クイックソートのプログラムなんですが、 セグメンテーション違反で実行出来ません。 どこがおかしいのでしょうか? int main(void) { FILE *fp; int a[10],b=0,n; clock_t start; double jikan; if( (fp = fopen ("quicksort.txt","r") ) == NULL ) { printf("ファイルが見つかりません : quicksort.txt\n"); exit(1); } while( fscanf(fp, "%d", &a[b]) != EOF ) { b++; } start = clock(); quick_sort(a,n); jikan = clock() - start; for(n = 0; n < b ; ++n) { printf("%d ",a[n]); } printf("計算時間 %.3f 秒 \n", jikan/CLOCKS_PER_SEC); return 0; } int partition(int a[], int l, int r) { int i,j,pivot,t; i = l-1; j = r; pivot = a[r]; for(;;) { while( a[++i] < pivot ) ; while( i < --j && pivot < a[j] ) ; if( i >= j ) break; t=a[i]; a[i]=a[j]; a[j]=t; } t=a[i]; a[i]=a[r];a[r]=t; return i; } void quick_sort_1(int a[],int l,int r) { int v; if( l >= r ) return; v = partition( a, l, r); if( l < v-1 ) quick_sort_1( a, l, v-1); if( v+1 < r ) quick_sort_1( a, v+1, r); } void quick_sort(int a[],int n) { quick_sort_1( a, 0, n-1); }

  • クイックソートがうまくいかない

    クイックソートの仕様はこうです。 (1)バラバラにランダムで入力した配列から基準値を設定する。 (2)前から順番に辿って行って基準値よりも大きいならば、基準値よりも後に移動、小さいならば、基準値よりも前に移動させる。(私のプログラムの場合は基準値を配列の一番目の数に設定しています。) (3)小さいほうと大きいほうの二つのグループに分かれたらまたそれらのグループごとにクイックソートにかける。 (4)二つのグループを分けることができなくなればソート完了。 動作させてみたところ関数QuickSortの中の「基準値より大きいか小さいかの仕分けの処理」の後で、再帰処理があるのですが、再帰ではなく無限ループになってしまっているようです。 自分では、この処理で無限ループをとめているつもりです。 if(youso==1) { return; } なぜこのようになってしまうのでしょうか お手数ですが、よろしくお願いいたします。 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define N 10 int k,q; void QuickSort(char mi,char hai[10],int youso) { char shoubox[10]; char bigbox[10]; int i,len,len2; k=0,q=0; /*もし配列haiの大きさが1ならば終了*/ if(youso==1) { return; } /*配列の2番目から最後まで基準値からの大小により仕分けしていく。大きいならば、配列bigboxに小さい*/ /*ならば配列shouboxにそれぞれ入れる。*/ for(i=1;i<youso;i++) { if(hai[i]>mi) { bigbox[k++]=hai[i]; } else { shoubox[q++]=hai[i]; } } /*仕分け処理はここまで*/ /*小さいほうの配列と大きいほうの配列をそれぞれクイックソートにかける再帰処理。*/ QuickSort(shoubox[0],shoubox,q); QuickSort(bigbox[0],bigbox,k); /*それぞれのソートが完了したら、配列haiに「小さいほうの配列」→「基準値」→「大きいほうの配列」 の順に値を代入していく。*/ len=strlen(shoubox); for(i=0;i<len;i++) { hai[i]=shoubox[i]; } hai[len]=mi; len2=strlen(bigbox); for(i=(len+1);i<len+len2;i++) { hai[i]=bigbox[i]; } /*代入処理ここまで。*/ } int main(void) { char array[N]; char m; int i,val,j; srand(time(NULL)); /*(1~10)までの数字をランダムに入力する処理*/ for(i=0;i<N;i++) { do{ val=rand()%10; for(j=0;j<i;j++) { if(val+'0'==array[j]) { break; } } }while(j<i); array[i]=val+'0'; } /*ランダムに値を入力する処理ここまで*/ m=array[0]; /*値配列の最初を基準値mに設定*/ QuickSort(m,array,N); /*基準値、配列、要素数を実引数として、クイックソートを呼び出す。*/ /*昇順に並べ替えた配列arrayを出力する。*/ for(i=0;i<N;i++) { printf("array[%d]=%c\n",i,array[i]); } return 0; }

  • クイックソートのピボットの値を基準に分割される配列の表示

    クイックソートのプログラミングしたのですが 何処にピボットの値を基準に分割される配列の表示 するプログラムをいれていいかもわからない だけでなく、どの様なプログラムを入れたらいいかも 解りません 作ったプログラムは #include <stdio.h> #define MAX 1000 #define FMAX 8 void quick(int a[],int left,int right); int main(void) { int kosu; int atai[MAX]; int i; char fname[FMAX+1]; FILE *fp; printf("並び替える整数の個数 : "); scanf("%d",&kosu); printf("データが格納されたファイル名:"); scanf("%s",fname); if((fp=fopen(fname,"r"))==NULL) { printf("%sファイルがfopenできませんでした。処理を終了します",fname); exit(1); } for(i=0;i<kosu;i++) { fscanf(fp,"%d",&atai[i]); } quick(atai,0,kosu-1); puts("昇順に並び替えました"); for(i=0;i<kosu;i++) { printf("%d番目の整数 : %d\n",i+1,atai[i]); } fclose(fp); return 0; } void quick(int a[],int left,int right) { int pl=left; int pr=right; int pivot; int tmp; int i; pivot=a[(pl+pr)/2]; printf("ピボットの値は%d\n",pivot); do{ while(a[pl]<pivot) { pl++; } printf("\n"); while(a[pr]>pivot) { pr--; } if(pl<=pr) { { tmp=a[pl]; a[pl]=a[pr]; a[pr]=tmp; } pl++; pr--; } }while(pl<=pr); if(left<pr) { quick(a,left,pr); } if(pl<right) { quick(a,pl,right); } } です 解るかた詳しく教えてください お願いします

  • クイックソート(C言語)

    こんにちは<_ _> クイックソートについての質問です。 左端を軸にクイックソートでデータを昇順にソートする プログラムを作ったのですがうまく動きません #include<stdio.h> void quick(int *,int,int); #define N 10 int main(void) { static int a[]={41,24,76,11,45,64,21,69,19,36}; int k,b=0; quick(a,0,N-1); for(k=0;k<N;k++) printf(" %d",a[k]); return 0; } void quick(int a[],int left,int right) { int s,t,i,j; t=right; i=left+1; j=a[left]; if(right>left){ while(1){ while(a[++i]>j); while(a[--t]<j && t>0); if(i>=t){ break; } s=a[i]; a[i]=a[t]; a[t]=s; } s=a[i]; a[i]=j; a[left]=s; quick(a,left,t-1); quick(a,t+1,right); } } 値の入れ替え、軸の入れ替えもしましたが結果として 「41 41 76 69 45 64 41 19 0 36」 このような結果で出力されてしまいます・・・ 時間に余裕のある方いましたらご指導をお願いします。 よろしくお願いします。<_ _>

  • 構造体の配列について

    構造体配列を使った簡単なプログラムを組んでいるのですが、以下のソースコードをコンパイルし、実行したのですが、うまくいきません。 どなたかお力をお貸しください。 ・やりたい事 配列に以下のようにデータをscanf関数を使って入れたいです。 ----[0]---[1]---[2]--- [0] 1 | "あ" | "猫" | [1] 2 | "い" | "亀" | [2] 3 | "う" | "狐" | -登録する内容 番号、名前、好きなもの動物 ■ソース #include <stdio.h> struct hyou { int box[3][3]; }; int main(){ struct hyou *da; int i; for(i=0;i<2;i++){ printf("番号:\n");   scanf("%d",&da->box[i][0]); printf("名前:\n");   scanf("%s",&da->box[i][1]); printf("好きなもの:\n");   scanf("%s",&da->box[i][2]); } //テスト(2件表示) for(i=0;i<2){ printf("番号:\n"); printf("%d",a->box[i][0]); printf("名前:\n"); printf("%s",a->box[i][1]); printf("好きなもの:\n"); printf("%s",a->box[i][2]); } } //構造体配列の意味が違っていたらすみません。 以上、宜しくお願いします。

  • 構造体とポインタ配列

    現在C言語の勉強をしております。 環境はwindowsXP、コンパイラはVC6.0です。 構造体と、ポインタの配列についてなのですが、 以下のような構造体が宣言されている時に、リスト構造にデータがいくつか入っているとします。 // 構造体 typedef struct address { unsigned char names[NAME_SIZE+1]; /* 名前 */ char tels[TEL_SIZE + 1]; /* 電話番号 */ struct address *prev; /* 前へのポインタ */ struct address *next; /* 次へのポインタ */ }Address, *a_pt; そのリスト構造を先頭要素か順番にポインタ配列に格納するには以下の方法ではおかしいでしょうか? /* ポインタ配列を用意する */ Address *array[MAX_COUNT]; /* top_ptは先頭のポインタです */ pt = top_pt; /* データがなくなるまで配列へ格納する */ while(pt != NULL){ array[count++] = pt; pt = pt->next; } /* 配列の最後はNULLとする */ array[count] = NULL; また、配列の中身を確認する方法としては、 printf("配列の中身:%s\n", array[0]->names); では、アドレスが表示されてしまうのかな・・と思ったら、accessViolationで落ちてしまいました・・・。 中身はどうしたらデバッグ出来ますでしょうか? そもそも、以下の2つは何か違いはありますか? Address *ptA[100]; a_pt ptB[100]; 皆さん、どうかよろしくお願いいたします。 理解不能な場合はご指摘ください。

専門家に質問してみよう