• 締切済み

クイックソートの再帰呼び出し後の記述について(特に配列の範囲)

アルゴリズムをすこしかじってみているのですが、いきなり躓いてしまいました。詳しい方にお聞きします。クイックソートの再帰呼び出し後のプログラムの記述がよくわかりません。(特に配列の範囲) QuickSort(Head,Tail)というプログラムがあるとします。最初の一連の処理が終わり、再帰呼び出しの部分で、 QuickSort(Head,Left-1)という前半部分を指定した再帰呼び出しとQuickSort(Right+1,Tail)という後半部分を指定した再帰呼び出しがされるとします。ここまでは分かるのですが、この再帰呼び出しのプログラムの実行を記述するとなるとどうなるのでしょうか?特に分からないのはこの再帰呼び出しでさらに再帰呼び出しされるQuickSortのカッコ内の配列の範囲がどのようになるのか、何か特別な記述はされるのかということです。あとソートの必要のないレベルまで来た場合の処理(記述)も分かりません。どなたかご教授願えないでしょうか?

みんなの回答

  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.2

クイックソートは、ピボット(分割値)を決め、データをピボット以下とそれ以外の2つに分けることを繰り返す方法です。 クイックソートの手順は、 (1)ピボットを決め、データをピボット以下とそれ以外に分ける (2)前半部分をクイックソートする(再帰呼び出し) (3)後半部分をクイックソートする(再帰呼び出し) これだけです。 >特に分からないのはこの再帰呼び出しでさらに再帰呼び出しされるQuickSortのカッコ内の配列の範囲がどのようになるのか、何か特別な記述はされるのかということです。 何が分からないのかが分かりませんが、QuickSort(Head,Tail)ですることは、HeadからTailまでの区間の配列データを処理するだけです。それ以外の範囲のデータは考える必要はありません。 >あとソートの必要のないレベルまで来た場合の処理(記述)も分かりません。 クイックソート(再帰呼び出し)するかどうかは、データ数で判断します。 データ数が1以下の場合はすでにソートされていますから、再帰呼び出しする必要はありません。

gayaldy
質問者

補足

理解力がなくすみません。(1)「QuickSort(Head,Tail)ですることは、HeadからTailまでの区間の配列データを処理するだけです。それ以外の範囲のデータは考える必要はありません。」とのことですが、質問で、再帰呼び出し後のHeadからTailの配列の始端と終端を書いたのですが、これが実行されるとその次の配列の始端と終端はどう示されるかということなのですが・・あと、「クイックソート(再帰呼び出し)するかどうかは、データ数で判断します。」とお書き頂きましたが、これはプログラムでどのように記述されるのでしょうか?

回答No.1

関連するQ&A

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

    クイックソートとはこういう仕様のソートのことです。 (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; }

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

    クイックソートの仕様はこうです。 (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; }

  • 再帰呼びだし

    再帰呼びだし 問題1 再帰呼び出しを用いてint型の配列({-9、8、-7、6、5、4、1、3、6、9、2、-14})の最小値を求めて出力するプログラムを作成せよ。関数名はmin_of_arrayとする。 問題2 同じく再帰呼び出しを用いてint型の配列({3、4、1、5、2})を小さい方から順番に求めて出力するプログラムを作成せよ。 再帰呼び出しが苦手で、じっくり解いていこうと思ったのですが、他の課題もあって、もう提出期限いっぱいいっぱいなので載せました。 どうかよろしくお願いします。

  • 再帰呼び出しを使いますか?

    趣味でプログラムをかじる程度なのですが、今まで自分はプログラムを作っていて再帰呼び出しを使ったことがありませんが、みなさんは良く使うのでしょうか? なかなか再帰呼び出しを考えるのが難しく自分のプログラムで適用すると良いところなど思い浮かびません。 再帰呼び出しをすると何か利点とかあるのでしょうか? 再帰呼び出しで無いと作るのが難しいプログラムなど今までありましたか?あればどんな処理だったかなど教えてください。

  • クイックソート

    N個のデータを降順に並び替えるプログラムをクイックソートで書きたいのですがよく分かりません。アルゴリズムの部分をどなたか教えてください。できれば詳しい説明もお願いします。

  • クイックソート

    クイックソートのプログラムを作ったのですがうまくいきません 汗 コンパイル時に sample1.c: In function ‘quicksort’: sample1.c:31: error: expected expression before ‘]’ token sample1.c:32: error: expected expression before ‘]’ token sample1.c:32: error: too few arguments to function ‘quicksort’ とでます。 まだアルゴリズムやCは勉強始めたばかりで基本的なところでつまって いるかもしれません。ご教授おねがいします。 /*クイックソート*/ #include<stdio.h> #define MAXDATA 10 #define swap(type,a,b) {type m; m = a; a = b; b = m;} void quicksort(int a[],int left ,int right) { int i,j,pivot; pivot = a[left]; i = left + 1; j = right; while(i <= j){ while(a[i]<pivot) i++; while(a[j]>pivot) j--; if(i<j){ swap(int,a[i],a[j]); i++; j--; } } swap(int,a[left],a[j]); quicksort(a[],left,j-1); quicksort(a[],j+1,right); } int main(void) { int k,j,sort[MAXDATA]; for(k=0;k < MAXDATA;k++) {printf("sort[%d]:",k); scanf("%d",&sort[k]);} for(k=0;k < MAXDATA;k++) printf("%3d",sort[k]); puts("ソートしますか? Yes:1 No:0 ///"); scanf("%d",&j); if(j==1){ quicksort(sort,0,MAXDATA-1); for(k=0;k < MAXDATA;k++) printf("%3d",sort[k]); } putchar('\n'); return(0); }

  • アプレットのクイックソート分割について教えて下さい

    JAVA アプレットでクイックソートの基本的な仕組みである分割についてのアプレットを作成したく色々と調べているのですが,再帰呼び出しを使ってソートするクイックソートの情報は沢山あるですが, 中央値を用いて中央値より大きいグループAと中央値よりも小さいグループBというように二つのグループに分ける分割のアプレットのサンプルプログラムは探していますが見つかりません. 分割について詳しいかたがいましたら情報を下さい, 宜しくお願いします.

  • クイックソートしながら重複要素削除アルゴリズム

    アルゴリズムが苦手な上、アルゴリズム解説自体C言語ベースで書かれ ている物が多く処理のイメージが沸かずクイックソートもコピペや既存 の関数で処理していて、満足に理解出来ていないのですが。 以下の問題を、お解かりになるかた教えて頂けませんでしょうか? ■問題 2万件位の数値データの中から重複要素を削除しながら昇順または降順で、 ソートするアルゴリズム(※1) ■条件 BASIC的(※2)な記述やプログラム中のコメントなどの形式でも構いま せん出来るだけ簡単に示して頂けると助かります。 補足 (※1)ソートする際、重複要素を消すともっと処理が早くなるのではと 思ったので。 目的は、処理の速さを求める事と、次回から応用が聞くよ うにソート自体を理解したいのでクイックソートで無くても構いません。 (※2)実際に動かなくても構いません、イメージが掴みやすい方が良いと    いう意味でとって下さい。

  • 再帰的処理について

    指定したURLのページのHTMLを取得しその中のリンクを再帰的に表示するプログラムを考えていますが再帰的な処理の部分がよく理解できません。教えて下さい。お願いします。

    • ベストアンサー
    • Perl
  • 非再帰のマージソートについて

    非再帰のマージソートを作成しているのですが、 上手いこと出来なくて困っています。 条件として配列の開始と終了のインデックスを指定して、 その間の要素だけをソートしたいのです。 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 どなたがおわかりの方がいらっしゃれば、 その方法を教えていただければ助かります。

専門家に質問してみよう