• 締切済み

アルゴリズムによる整列方法について

以下の問題を授業外課題として出されましたがわかりません。身近に分かる人物もいません。 先生も答えてくれません。 解答お待ちしております。 1.以下の文章の空欄を埋めよ.但し,((14)),((15)) については,選択肢から最も適切なものを選び,記号で答えよ.加えて,解答の過程を詳しく述べよ。 高速な整列として以下のアルゴリズムによる方法を考える.以下では,整数データを昇順に配列するも のとする. 前段階として,データを半々に二つのグループ I と II に分割し,それぞれを独立に整列する. while (両グループに要素が残っている) do    if (グループ I の最小要素 < グループ II の最小要素)    then  グループ I の最小要素を出力場所に移し,グループ I からは削除する    else  グループ II の最小要素を出力場所に移し,グループ II からは削除する    endif done while (グループ I に要素が残っている) do  グループ I の要素を出力場所に移し,グループ I からは削除する done while (グループ II に要素が残っている) do  グループ II の要素を出力場所に移し,グループ II からは削除する done この整列に要する計算量 T(n) を求める.但し,n は整列するデータの量である.前段階の整列では,半分のデータ量の整列を 2 回行うので ((1)) だけの計算を要する.次に,3 個の while 反復のいずれについても, 「反復を 1 回行うごとに要素が一つだけ出力場所に移動する」 ことから,3 個を合計すると反復の中身は正確に ((2)) 回実行されることが分かる.1 回の実行に a だけの時間がかかるものとすれば,全体で ((3)) となる.従って次の関係式が成り立つ. T(n) = ((4)) 簡単のため,n = 2^p であるとすると, T(n) = ((5))×T(2^((6)) ) + ((7))    = ((8)) × T(2^((9)) ) + 2 × ((7))    ・    ・    ・    = ((10)) × T(2^0) + ((11)) T(2^0) = ((12)) なので,T(n) を a と n のみを用いて表すと, T(n) = ((13)) であり,これは, ((14)) に比例し,計算量のオーダーは ((15)) といえる. ((14)),((15)) の選択肢 a. n b. n^2 c. 2^n d. n log n e. log n f. いわゆる「指数オーダー」であり,アルゴリズムとして全く実用に耐えない g. いわゆる「バカソート」と同じであり,n がごく小さい場合を除いて実用には適さない h. 経験上最速とされるソート法には及ばないが,それほど大きくない n に対しては実用に耐える i. 経験上最速とされるソート法と同じであり,十分大きい n に対しても実用に耐える

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

このアルゴリズムはやってないかもしれませんが、他のアルゴリズムや、その「計算量」の考え方はやってますよね? 何の前振りも無しに、こんな問題を出すとは思えません。 他のアルゴリズムだはどんなことやっていたか、復習してみましょう。 n個の整列にかかる時間がT(n)なら、n/2個の整列にかかる時間はT(n/2)です。 (4)は、具体的な計算をするのではなく、T(n/2)や他の値を使って、T(n)との関係だけを求めておきます。 実際の値の計算は、とりあえず、置いておきます。 ※ (5)以降が、その具体的な計算をしていくところです。 コンピュータになったつもりで、御自身で具体的にやってみるのもよいでしょう。 トランプを用意します。 全部使ってもよいのですが、わかりにくいので、スペードだけを使います(ハートでもいいですけど) 場に J Q K と置きます。 1~10のカードを裏返して混ぜ、5枚ずつに分割します。 片方を、小さいカードが上になるように順番に並べて、Jの横に置きます。 もう片方は同様にしてQの横に置きます。 例えば、こういう状態になったとします J; 4 Q: 1 K; これが「前段階として,データを半々に二つのグループ I と II に分割し,それぞれを独立に整列する.」の部分です。 JがグループI,QがグループIIです。 ここから、アルゴリズムに従って処理します。 まず最初に。 JもQもあるので、「while (両グループに要素が残っている)」の部分です。 各グループの最小値は、一番上です。 4 と 1 を比べれば 1が小さいです。 従って、 1 を QからKへ移動します。 J; 4 Q: ↓ K; 1 ここまでが「1回」で、時間は a だけかかります。 ここで、 JとQは整列してあるので、最小値を探すには、一番上を見ればいいことになります。 人間だと、5枚くらいなら、全部表にして並べて、一番小さいカードを探しても大して苦ではありません。 ですが、コンピュータにはそんなことはできません。いちいち全部のカードを調べて探さなければなりません。 それを、「整列しておいて、先頭だけを見る」とすることで、コンピュータでも楽に最小値を探すことができます。 これを繰り返していくと、 J; 無し Q: 9 K; 1 2 3 4 5 6 7 8 のような状態になります。ここからは 「while (グループ I に要素が残っている) do」 「while (グループ II に要素が残っている) do」 に従って、残っているカードを1枚ずつKへ移動します 全部終わると J; 無し Q: 無し K; 1 2 3 4 5 6 7 8 9 10 とKの整列ができあがります。 かかる時間は T(10)=「Jに並べる時間」+「Qに並べる時間」+ 「Kへ移動させた回数」× a になるのがわかると思います。 JとQを並べるのに、このアルゴリズムを使えば、「5枚並び換える時間」ですから T(10)=T(5)+T(5) + 「Kへ移動させた回数」× a になります。 「Kへ移動させた回数」は....もうわかりますよね? 実はアルゴリズムは有名なもので、名前も付いています。 それで検索すれば解説も「答え」も見つかってしまうのですが....とりあえずは黙っておきます。 あと「バカソート」って何のことだろう? 計算量の話ならバブルソートかな、とも思いますが、「バカ」って意味では、ボゴソート、ボゾソートの方が「バカ」ですし。

回答No.3

学術的には名前があるのかもしれませんが、 ナチュラルマージソートをちょっと非効率にしたようなソートですね。 質問にはありませんが、分割は1個までやってしまうのでしょうね。 #実際にはデータを一度スイープすればどこまで分割が必要か判断できるので #1個まで分解したりはしないです。 T(2^p) =2 X T(2^(p-1)) + a x 2^(p) =2 x (2 x T(2^(p-2)) + a x 2^(p-1)) + a x 2^(p) = 4 x T(2^(p-2)) + 2 x a x 2^(p) = 2^p x T(1) + pa x 2^p = nT(1) + pan = nT(1) + logn・an なので a に比例して nlogn のオーダーなのでしょう。 オンラインで書いたので、間違っていたらすいません。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

まず、あなたがどこまで埋めることができたのか、教えてくれませんか? ほとんどは、 T(x),n,p,a を使った式です。 2^p=n より、 p = log n ということも利用しましょう。 データ量n個の時間がT(n)なら、「半分のデータ量」はn/2で、その時間はT(n/2)です。 14,15の選択肢ですが、 14には a~e,15にはf~iが入るのはわかるかと思います。 14が決まれば15が決まります。また、相手の無い選択肢があります。 それはわかりますか? ※ hとiは解釈にちょっと困る

yurufuwari
質問者

お礼

#1さんにもお答えしたとおり、全く分からないのです。最初から、何を言っているのかわかりません。 前段階の話からついていけません。 前段階で整列?が必要なのでしょうか? 何回?それはどのようにすれば求まりますか?(n-2)回とかでしょうか? 14と15の選択肢ですが、選択肢を見た感じ、片方(14)にlogなどが入り、もう片方(15)は言葉だろうな、という漢字のレベルでは認識していました。

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

「先生も答えてくれません」て, そりゃそうでしょう. そこで簡単に答えてしまうようでは, それこそ「授業外課題」になどなりもしないんだから. で, なにをどのくらい考えた末の「わからない」ですか?

yurufuwari
質問者

お礼

ありがとうございます。正直「全く分からない」です。 というのも、先生はアルゴリズムに関して全く授業で触れていません。買わされた教科書にも載っていません。なのにもかかわらず、この問題から試験を作成するとおっしゃっていました。「そういえば、こんな問題があるから、解いておいてね、テストに出すから」とのことです。なので、周りの友人たちもわからず、疲弊しきっています。

関連するQ&A

  • アルゴリズムについて

    大学の授業の課題のアルゴリズムについてなのですが、内容的に頭がついて行けず、一切分かりません。問題内容は、最小値を求めるアルゴリズム(必要な箇所を修正して下さい)です。 どなたか詳しい方いらっしゃいますでしょうか? よろしくお願いいたします。 M = -9999 データX入力 while X ≠ 9999 Y M < X N   M = X   データX入力   Mを出力

  • クイックソートでの整列

    10個~20個程度の数列をキーボードから入力し、降順に整理し途中経過と整列後の状態を表示するプログラムを作りなさい。 このような課題が出ているのですが、よくわかりません。授業中に この2つのプログラムを応用すればできるといわれたプログラムがあるのですが、コンパイルするとエラーがたくさん出てきます。 ヒントを教えてください。 1.c #include <stdio.h> #include <stdlib.h> quick_sort(int a[], int l, int r); main(int argc, char *argv) { int i, x[100], n; n = atoi(argv[1]); for(i = 0;i< n;i++); scanf("%d", %x[i]); quick_sort(x, n); printf("sort\n"); for(i = 0;i<n; i++){ printf("%d\n", x[i]); } return ; } 2.c quick_sort(int a[], int l, int r) { int v,i,j,t; if(r>1) { v=a[r]; i=l-1; j=r; while(1) { while(a[++i]<v); while(a[--j]>v) if(j==l)break; if(i>=j)break; t=a[i];a[i]=a[j];a[j]=t; } a[r]=a[i];a[i]=v; quick_sort(a,l,i-1); quick_sort(a,i+1,r); } }

  • 全順序集合Aが整列集合でない⇔Z(-)⊂A

    次の問題を解いているのですが…。 よろしくお願い致します。(i)の必要性の証明で困ってます。 [[問] 次の(i),(ii)を証明せよ。Z(-)を負整数全体の集合とする。 (i) 全順序集合Aが整列集合でない⇔Z(-)⊂A. (ii) Aが全順序集合且つAの任意の可算な部分集合が整列集合⇒Aは整列集合 [(i)の証] 十分性を示す。 A=Z(-)と採れば{2z;z∈Z(-)}⊂Aでしかもこの部分集合は最小値を持たない。 よってAは全順序だが整列集合とならない。 必要性を示す。 ∃B⊂A;minBが存在しない。その時,Z(-)⊂Aを言えばいいのですがどうすればいえますでしょうか? [(ii)の証] 対偶「Aは整列集合でないならば(Aは全順序集合でない∨(∃B⊂A;Bは可算だが非整列))」となる。 もし,Aが非整列ならAは全順序ではない場合もありうる。 もし,Aが非整列だがAは全順序の場合,∃B⊂A;(Bは可算∧minBが存在しない)でなければならない。これは,(i)の必要性よりZ(-)⊂A (Z(-)は可算)と言えるのでB:=Z(-)と採ればよい。 この時,B非整列なので(∵最小値を持たないBの部分集合としてBを採ればよい) Aが全順序集合且つAの任意の可算な部分集合が整列集合⇒Aは整列集合 が示せた。となったのですがこれで正しいでしょうか?

  • データ構造とアルゴリズムの問題です

    要素数がnである配列aの要素の最大値を求めるアルゴリズムのループ端によるフローチャートを完成せよ(前判定繰返し) max =a[0] i=1; while i<n do{ if(a[i]>max)max=a[i]; i++; } a[0] → max 1 → i 前判定繰返し □ | yes a[i]□max-----| |        □      NO i+1 → i 前判定繰返し □の中を埋めるんですが教えてください

  • データ構造とアルゴリズムの問題です

    要素数がnである配列aの要素の合計を求めるアルゴリズムのループ端によるフローチャートを完成せよ(後判定繰返し) sum =a[0] i=1; do{sum=sum+a[i]; i++; }while i<n; a[0] → sum 1 → i 後判定繰返し | □→sum; i+1 → i | □ 後判定繰返し □の中を埋めるんですが教えてください

  • クイックソートの分割アルゴリズムについて。

    int partition(int[] a,int i,int j,int x){ int l=i,r=j; // 検索が交差するまで繰り返します while(l<=r){ // 軸要素以上のデータを探します while(l<=j && a[l]<x) l++; // 軸要素未満のデータを探します while(r>=i && a[r]>=x) r--; if(l>r) break; int t=a[l]; a[l]=a[r]; a[r]=t; l++; r--; } return l; } この部分でたとえば数値が{5,9,4,2,8,6}と与えられているとしたらどのような交換手順で分割していくのでしょうか?

  • 走査アルゴリズムについて

    n個の要素の配列x[]について 配列xの連続した要素(部分配列)でその和が最大になるものを見つけて、 その和を出力するアルゴリズムについてです。 これなのですが解き方の考え方に 「x[0...n]までの部分配列の最大和は、x[0...n-1]の部分配列の最大和か、x[n]から左方向に伸びた配列の和のいずれかである。」 とあり プログラムには float maxSoFar(float x[], int length){ float maxsofar = 0; float maxendinghere = 0; for(int i = 0; i < length; i++){ maxendinghere = max(0.0f, maxendinghere + x[i]); maxsofar = max(maxsofar, maxendinghere); } return maxsofar; } とあるのですが、アルゴリズムの仕組みがよくわかりません。 なぜ上のような説明でこのようにプログラムできるのかが わからないので、どなたかうまい説明できる人お願いします><

  • 最小の整数が,何番目に入力されたものかを出力したい

    先日、 「一つの整数をキーボードから入力する。これをn とする。続いてn 個の整数をキーボードから入力する(値は100 以下と仮定してよい)。その後、n 個の整数の中で最小のものを出力したい」 という質問をした者です。 今度は出力された最小の整数が,何番目に入力されたものか を出力したいのですが、どうすればいいですか? 困ってるんでお願いします。 ちなみに、前回の質問の答えはこうなりました。↓ #include <stdio.h> int main(void) { int n, i, t, min=0; scanf("%d",&n); for (i=0; i < n; i++){ scanf("%d",&t); if (i==0){ min=t; } if (min > t) { min=t; } } printf("\n最小:%d", min); return (0); }

  • 整列集合を添数集合とする任意の互いに素な整列集合の族も整列?

    下記の問題(2)で質問なのですが… (1) Let A_1 and A_2 be disjoint sets, well-ordered by <' and <", respectively. Define an order relation on A_1∪A_2 by letting a<b either if a,b∈A_1 and a<' b,or if a,b∈A_2 and a <" b,or if a∈A_1 and b∈A_2.Show that this is a well-ordering. (2) Generalize (1) to an arbitrary family of disjoint well-ordered sets, indexed by a well-ordered set. 「(1) A_1とA_2を整列集合で互いに素とする。それぞれの順序<'と<"とする。 A_1∪A_2の順序<をa,b∈A_1∪A_2がa∈A_1,b∈A_2の時,a<bとし,a,b∈A_1ならa<bはa<'bの意味とし,a,b∈A_2ならa<bはa<"bの意味とする。この時、A_1∪A_2は整列となる事を示せ。 (2) (1)を整列集合を添数集合とする任意の互いに素な整列集合の族に一般化せよ。」 [(1)の証明] ∀B⊂A_1∪A_2に対し,B⊂A_iなら∃minB(∵A_iは整列) (i=1,2) B∩A_1≠φ且つB∩A_2≠φならば∃minB∩A_1,∃minB∩A_2なので minB:=min{minB∩A_1,minB∩A_2}と採ればよい。 で大丈夫かと思います。 [(2)の証明] 整列な添数集合をNとしA_i(i∈N)の順序を <_i とすると B∩A_i≠φ(i∈N)の時,集合{minB∩A_1,minB∩A_2,…}には最小元があるとは限りませんよね。 (2)はどのようにして示せばいいのでしょうか?

  • 整列(ソート)

    昇順(1,1,1・・2,2,2・・・9999,9999)に並び替えるプログラムを実装してください.  (1)挿入ソート  (2)選択ソート  (3)バブルソート  (4)クイックソート なお,整列アルゴリズムの実装は,sort_main 関数でプログラムを記述してください.また,必要あれば,別関数を定義しても良い. 特に(1),(2)について教えてください。 #include <stdio.h> #include <time.h> // 定数宣言 #define COUNT 100000 // データ数を指定 #define INFILE "07sort.txt" // 入力ファイルを指定 #define SORTFILE "out.txt" // 出力ファイルを指定 // プロトタイプ宣言 void sort_main(int *); void getFile(int *); void outFile(int *); double getFuncTime(clock_t, clock_t); // ソート(並び替え)メイン関数 void sort_main(int *array){ // ソート(並び替え)の処理を本関数で実現すること // 処理をまとめたい場合は,別関数を定義すること // *(array) = 10; <-- data[0] = 10;  と同じ // *(array + 10) = 100; <-- data[10] = 100; と同じ } // プログラムのメイン関数 int main(){ // 変数宣言 clock_t start,end; // 開始&終了時間を格納 int data[COUNT]; // ファイル内のデータを格納 // ファイルからデータの読み込み getFile(data); // 処理開始時間の設定 start = clock(); // ソート関数の呼出し sort_main(data); // 処理終了時間の設定 end = clock(); /// 処理にかかった時間の出力 printf("--- Sort Time is %.2f sec. ---\n", getFuncTime(start, end)); // 配列に保存されたデータの格納 outFile(data); } void getFile(int *cur){ FILE *fp; fp = fopen(INFILE, "r"); while(fscanf(fp,"%d", cur) != EOF){ cur++; } fclose(fp); } void outFile(int *cur){ FILE *fp; int i; fp = fopen(SORTFILE, "w"); for(i=0; i<COUNT; i++){ fprintf(fp, "%d\n", *(cur+i)); } fclose(fp); } double getFuncTime(clock_t start, clock_t end){ return (double)(end-start)/CLOCKS_PER_SEC; }