アルゴリズム学習のソート(6)--ソートのマージ
一.アルゴリズムの説明
集計ソートは、1つのシーケンスを2つの長さの等しいサブシーケンスに分割し、各サブシーケンスの集計ソートを呼び出してソートし、それらを1つのシーケンスにマージします.2つのサブシーケンスをマージするプロセスを集計と呼び、集計ソートの実行時間は入力配列の要素との組合せに依存しません.
集計ソートは常に再帰的に呼び出され、サブシーケンスをソートします.再帰的に終了する条件は、配列に要素が1つしか含まれていない場合、関数は他の操作を行わずに直接戻ります.
二.時間の複雑さ
集計ソートは毎回、シーケンスを等しい2つのサブシーケンスに分割するので、集計ソートの時間的複雑さは、入力配列中の要素がソートされているかどうかに関係なく、最良の場合、平均および最悪の場合の時間的複雑さはO(nlogn)である.
三.くうかんふくざつさ
集計ソートの集計プロセスでは2つのサブシーケンスを集計する必要があり,配列のような構造を用いてデータを格納する場合は,2つのサブシーケンスを余分な空間にコピーして集計する必要があるため,格納構造として配列を用いると空間複雑度はO(n)となる.データの格納構造としてチェーンテーブルを使用する場合、2つのサブシーケンスを集計するプロセスは、チェーンテーブルの要素を別のチェーンテーブルに配置するだけであり、要素の値をコピーする必要はなく、空間的複雑度はO(1)である.
四.C++実装
五.参考文献
[1] Shaffer C A. Practical Introduction to Data Structure and Algorithm Analysis (C++ Edition)[J]. 2002.
[2]科曼and金貴、アルゴリズム導論:機械工業出版社、2006.
[3]T.H.Cormen,C.E.Leiserson,R.L.Rivest,and C.Stein,「アルゴリズム導論(影印版)」,ed:北京:高等教育出版社.
集計ソートは、1つのシーケンスを2つの長さの等しいサブシーケンスに分割し、各サブシーケンスの集計ソートを呼び出してソートし、それらを1つのシーケンスにマージします.2つのサブシーケンスをマージするプロセスを集計と呼び、集計ソートの実行時間は入力配列の要素との組合せに依存しません.
集計ソートは常に再帰的に呼び出され、サブシーケンスをソートします.再帰的に終了する条件は、配列に要素が1つしか含まれていない場合、関数は他の操作を行わずに直接戻ります.
二.時間の複雑さ
集計ソートは毎回、シーケンスを等しい2つのサブシーケンスに分割するので、集計ソートの時間的複雑さは、入力配列中の要素がソートされているかどうかに関係なく、最良の場合、平均および最悪の場合の時間的複雑さはO(nlogn)である.
三.くうかんふくざつさ
集計ソートの集計プロセスでは2つのサブシーケンスを集計する必要があり,配列のような構造を用いてデータを格納する場合は,2つのサブシーケンスを余分な空間にコピーして集計する必要があるため,格納構造として配列を用いると空間複雑度はO(n)となる.データの格納構造としてチェーンテーブルを使用する場合、2つのサブシーケンスを集計するプロセスは、チェーンテーブルの要素を別のチェーンテーブルに配置するだけであり、要素の値をコピーする必要はなく、空間的複雑度はO(1)である.
四.C++実装
#include <iostream>
#include "Sort.h"
#include "randomarray.h"
bool Merge(std::vector<int>::iterator Ite, int LeftIndex, int RightIndex)
{
if (LeftIndex >= RightIndex)
{
return false;
}
if (LeftIndex == (RightIndex - 1))
{
return true;
}
int Mid = (LeftIndex + RightIndex) / 2;
// copy the array
std::vector<int> LeftArray;
for (int Index = LeftIndex; Index < Mid; Index++)
{
int Tmp = *(Ite + Index);
LeftArray.push_back(*(Ite + Index));
}
std::vector<int> RightArray;
for (int Index = Mid; Index < RightIndex; Index++)
{
int Tmp = *(Ite + Index);
RightArray.push_back(*(Ite + Index));
}
// merge the sub array
for (int Index_left = 0, Index_right = 0, Index = LeftIndex;
Index < RightIndex;
Index++)
{
// Ended merge the left array
if (Index_left >= LeftArray.size())
{
int Tmp = RightArray[Index_right];
*(Ite + Index) = RightArray[Index_right++];
continue;
}
// Ended merge the right array
if (Index_right >= RightArray.size())
{
int Tmp = LeftArray[Index_left];
*(Ite + Index) = LeftArray[Index_left++];
continue;
}
// merge the two array
if (RightArray[Index_right] > LeftArray[Index_left])
{
int Tmp = LeftArray[Index_left];
*(Ite + Index) = LeftArray[Index_left++];
}
else
{
int Tmp = RightArray[Index_right];
*(Ite + Index) = RightArray[Index_right++];
}
}
return true;
}
bool MergeSort(std::vector<int>::iterator Ite, int LeftIndex, int RightIndex)
{
// return false if the LeftIndex >= RightIndex
if (LeftIndex >= RightIndex)
{
return false;
}
// return true when there are only one element in the array
if (LeftIndex == (RightIndex - 1))
{
return true;
}
// split the array to two sub array
int Mid = (LeftIndex + RightIndex) / 2;
MergeSort(Ite, LeftIndex, Mid);
MergeSort(Ite, Mid, RightIndex);
// Merge the sub array
return Merge(Ite, LeftIndex, RightIndex);
}
bool MergeSort(std::vector<int>& Array)
{
int Size = Array.size();
if (Size == 0)
{
return false;
}
if (Size == 1)
{
return true;
}
return MergeSort(Array.begin(), 0, Size);
}
五.参考文献
[1] Shaffer C A. Practical Introduction to Data Structure and Algorithm Analysis (C++ Edition)[J]. 2002.
[2]科曼and金貴、アルゴリズム導論:機械工業出版社、2006.
[3]T.H.Cormen,C.E.Leiserson,R.L.Rivest,and C.Stein,「アルゴリズム導論(影印版)」,ed:北京:高等教育出版社.