web-dev-qa-db-ja.com

ソートとO(n log n)の謎をマージ

私はすべての説明を読みます ここ ですが、まだ確信がありません。私はmergesortはn * nだと思います、そして私は私が間違っていることを知っていますが、どこにいるかはわかりません。これが私が思うことです:

8つの要素をソートしていて、これがアルゴリズムであると仮定します(私が正しい考えを持っていると仮定します)。

doSort(int begin, int end, int[] arr) {
    if(end != begin) {
        int mid = begin + (end - begin)/2;
        doSort(begin,mid);
        doSort(mid + 1, end);
        merge(arr, begin, mid, mid + 1, end);
    }  
}
merge(int[] arr,int i_begin, i_end, j_begin, j_end) {
// Do the comparison and all that
}

今私の理解によると、merge()自体は複雑なO(n)を持っています。今度はdoSort()が何回呼び出され、それゆえにmerge()が呼び出されたかを見てみましょう。 doSort()は、次のインデックスに対して呼び出されます。

  1. 0〜7
  2. 0〜3
  3. 4-7
  4. 0〜1
  5. 2-3
  6. 4-5
  7. 6-7

これは7回ですO(n)とすると、8つの要素を並べ替えます。同様に、16要素の場合、merge()は15回呼び出されます。したがって、配列をそれぞれ半分に分割しますが時間、私たちは決して他の半分を排除していません。これを、各ステップでツリーの半分を排除するBST検索と比較してください。 )そして、マージソートの場合、マージをn-1回呼び出し、マージがo(n)演算を必要とするたびに、O(n * n)を呼び出します。

どこが間違っているのですか?任意の提案をいただければ幸いです。

2
Mustafa

並べ替えは1,024個の数値を言い、2つの512要素配列の1つのマージを実行します。 2つの256要素配列の2つのマージ、2つの128要素配列の4つのマージ、8つのtims 64要素、...、2つの1要素配列の512マージを実行します。

単一の最大マージの時間(1 x 512要素)とマージの総数(1,023マージ)を確認したところ、半分のマージが1つの要素配列であり、残りのマージの半分がちょうどであることに気づかなかった2要素配列など。マージの各セットはn = 1024ステップ(1024エレメントの結果で1マージ、512エレメントの結果で2マージ、...、2エレメントの結果で512マージ)をとり、log2(n)= 10セットのマージがあります。合計10 x 1024または(n log2 n)ステップ。

3
gnasher729

マージソートの複雑さはO(nlogn)であり、O(n * n)ではありません。

マージソートは、分割統治アルゴリズムです。 3つのステップで考えてみてください。

除算ステップは、各サブ配列の中点を計算します。この各ステップは単にO(1)の時間を要します。征服ステップは、n/2(偶数)エレメントの2つのサブ配列をそれぞれ再帰的にソートします。マージステップは、O(n)時間。

ここで、ステップ1と3の場合、つまりO(1)とO(n)の間では、O(n)の方が高くなります。ステップ1と3が合計でO(n)時間かかることを考えてみましょう。ある定数cのcnであるとしましょう。

これらのステップは何回実行されますか?

これについては、下のツリーを見てください。上から下までの各レベルについて、レベル2は、それぞれ長さがn/2の2つのサブ配列でmergeメソッドを呼び出します。ここでの複雑さは2 *(cn/2)= cnレベル3は、長さがそれぞれn/4の4つのサブ配列に対してマージメソッドを呼び出します。ここでの複雑さは4 *(cn/4)= cnなどです...

現在、この木の高さは、指定されたnに対して(logn + 1)です。したがって、全体的な複雑さは(logn + 1)*(cn)です。これは、マージソートアルゴリズムのO(nlogn)です。

1
Jainul Vaghasia