Mergesortは、分割統治アルゴリズムであり、入力が繰り返し半分になるため、O(log n)です。しかし、それはO(n)ではありませんか?入力が各ループで半分になっている場合でも、各半分の配列でスワッピングを実行するには、各入力項目を反復する必要がありますか?これは本質的に漸近的ですO(n)私の心の中で。可能であれば、例を挙げて、操作を正しくカウントする方法を説明してください!私はまだ何もコーディングしていませんが、オンラインでアルゴリズムを調べています。私はまた、マージソートの動作を視覚的に示すためにウィキペディアが使用しているもののgifも添付しました。
O(log(n))ではなく、O(n * log(n))です。正確に推測したように、入力全体を反復処理する必要があり、これはO(log(n))回発生する必要があります(入力は半分にできるO(log(n))回)。log(n)回繰り返されたn個のアイテムはO(n log(n))を与えます。
比較ソートはこれより速く動作できないことが証明されています。基数ソートなどの入力の特別なプロパティに依存するソートのみが、この複雑さを克服できます。マージソートの一定の要素は通常それほど大きくありませんが、複雑性が低いアルゴリズムほど時間がかかりません。
マージソートの複雑さはO(nlogn)であり、O(logn)ではありません。
マージソートは、分割統治アルゴリズムです。 3つのステップで考えてみてください。
ここで、ステップ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)はマージソートアルゴリズムの場合です。
画像クレジット: Khan Academy
マージソートは再帰的なアルゴリズムであり、時間の複雑さは次の再帰関係として表すことができます。
T(n) = 2T(n/2) + ɵ(n)
上記の繰り返しは、Recurrence TreeメソッドまたはMasterメソッドを使用して解決できます。これはマスターメソッドのケースIIに該当し、再発の解はɵ(n log n)です。
マージソートは常に3つのケース(最悪、平均、最良)でɵ(nLogn)です。これは、マージソートが常に配列を2つに分割し、2つの半分をマージするのに線形時間を要するためです。
入力配列を2つの半分に分割し、2つの半分に対して自身を呼び出してから、ソートされた2つの半分をマージします。 merg()関数は、2つの半分をマージするために使用されます。 merge(arr、l、m、r)は、arr [l..m]とarr [m + 1..r]がソートされていると想定し、ソートされた2つのサブ配列を1つにマージする重要なプロセスです。詳細については、次のC実装を参照してください。
MergeSort(arr[], l, r)
If r > l
1. Find the middle point to divide the array into two halves:
middle m = (l+r)/2
2. Call mergeSort for first half:
Call mergeSort(arr, l, m)
3. Call mergeSort for second half:
Call mergeSort(arr, m+1, r)
4. Merge the two halves sorted in step 2 and 3:
Call merge(arr, l, m, r)
図を詳しく見ると、サイズが1になるまで配列が2つの半分に再帰的に分割されていることがわかります。サイズが1になると、マージプロセスが実行され、完全な配列になるまで配列のマージが開始されます。合併。
比較ベースのソートアルゴリズムには下限????(n*log(n))
があります。つまり、比較ベースのソートアルゴリズムでO(log(n))
時間の複雑さを持つことはできません。
ちなみに、マージソートはO(n*log(n))
です。このように考えてください。
_[ a1,a2, a3,a4, a5,a6, a7,a8 .... an-3,an-2, an-1, an ]
\ / \ / \ / \ / \ / \ /
a1' a3' a5' a7' an-3' an-1'
\ / \ / \ /
a1'' a5'' an-3''
\ / /
a1''' /
\
a1''''
_
これは逆二分木に見えます。
入力サイズをn
とします。
各_a_n
_は要素のリストを表します。最初の行の_a_n
_には要素が1つしかありません。
各レベルで、平均のマージコストの合計はn
です(コストが低いコーナーケースが存在します[1])。そして、木の高さはlog_2(n)
です。
したがって、マージソートの時間の複雑さはO(n*log_2(n))
です。
[1]すでにソートされているリストでソートする場合、これはベストケースと呼ばれます。コストは
n/2 + n/4 + n/8 + .... + 1 = 2^log_2(n) -1 ~ O(n)
に削減されました。 (長さn
が2の累乗であると想定)