私はマージソートの理論を研究しましたが、C++でそれを実装する方法については何も知りません。私の質問は、マージソートは再帰的に配列を作成するということです。しかし、実装する場合、実行時に配列を作成するにはどうすればよいでしょうか。またはこれに対する一般的なアプローチは何ですか?
ありがとう。
質問に答えるには:実行時に動的なサイズの配列を作成するには、を使用しstd::vector<T>
ます。理想的には、これらのいずれかを使用して入力を取得します。そうでない場合は、それらを変換するのは簡単です。たとえば、次のような2つの配列を作成できます。
template <typename T>
void merge_sort(std::vector<T>& array) {
if (1 < array.size()) {
std::vector<T> array1(array.begin(), array.begin() + array.size() / 2);
merge_sort(array1);
std::vector<T> array2(array.begin() + array.size() / 2, array.end());
merge_sort(array2);
merge(array, array1, array2);
}
}
ただし、動的配列の割り当ては比較的遅いため、通常は可能な限り避ける必要があります。マージソートの場合、元の配列のサブシーケンスをソートして、それらをインプレースマージすることができます。std::inplace_merge()
双方向イテレータを要求しているようです。
ここのコードに基づく:http://cplusplus.happycodings.com/algorithms/code17.html
// Merge Sort
#include <iostream>
using namespace std;
int a[50];
void merge(int,int,int);
void merge_sort(int low,int high)
{
int mid;
if(low<high)
{
mid = low + (high-low)/2; //This avoids overflow when low, high are too large
merge_sort(low,mid);
merge_sort(mid+1,high);
merge(low,mid,high);
}
}
void merge(int low,int mid,int high)
{
int h,i,j,b[50],k;
h=low;
i=low;
j=mid+1;
while((h<=mid)&&(j<=high))
{
if(a[h]<=a[j])
{
b[i]=a[h];
h++;
}
else
{
b[i]=a[j];
j++;
}
i++;
}
if(h>mid)
{
for(k=j;k<=high;k++)
{
b[i]=a[k];
i++;
}
}
else
{
for(k=h;k<=mid;k++)
{
b[i]=a[k];
i++;
}
}
for(k=low;k<=high;k++) a[k]=b[k];
}
int main()
{
int num,i;
cout<<"*******************************************************************
*************"<<endl;
cout<<" MERGE SORT PROGRAM
"<<endl;
cout<<"*******************************************************************
*************"<<endl;
cout<<endl<<endl;
cout<<"Please Enter THE NUMBER OF ELEMENTS you want to sort [THEN
PRESS
ENTER]:"<<endl;
cin>>num;
cout<<endl;
cout<<"Now, Please Enter the ( "<< num <<" ) numbers (ELEMENTS) [THEN
PRESS ENTER]:"<<endl;
for(i=1;i<=num;i++)
{
cin>>a[i] ;
}
merge_sort(1,num);
cout<<endl;
cout<<"So, the sorted list (using MERGE SORT) will be :"<<endl;
cout<<endl<<endl;
for(i=1;i<=num;i++)
cout<<a[i]<<" ";
cout<<endl<<endl<<endl<<endl;
return 1;
}
@DietmarKühlのマージソート方法を完了しました。それがすべてに役立つことを願っています。
template <typename T>
void merge(vector<T>& array, vector<T>& array1, vector<T>& array2) {
array.clear();
int i, j, k;
for( i = 0, j = 0, k = 0; i < array1.size() && j < array2.size(); k++){
if(array1.at(i) <= array2.at(j)){
array.push_back(array1.at(i));
i++;
}else if(array1.at(i) > array2.at(j)){
array.push_back(array2.at(j));
j++;
}
k++;
}
while(i < array1.size()){
array.push_back(array1.at(i));
i++;
}
while(j < array2.size()){
array.push_back(array2.at(j));
j++;
}
}
template <typename T>
void merge_sort(std::vector<T>& array) {
if (1 < array.size()) {
std::vector<T> array1(array.begin(), array.begin() + array.size() / 2);
merge_sort(array1);
std::vector<T> array2(array.begin() + array.size() / 2, array.end());
merge_sort(array2);
merge(array, array1, array2);
}
}
選択した回答を再配置し、配列にポインターを使用し、数値カウントのユーザー入力が事前定義されていません。
#include <iostream>
using namespace std;
void merge(int*, int*, int, int, int);
void mergesort(int *a, int*b, int start, int end) {
int halfpoint;
if (start < end) {
halfpoint = (start + end) / 2;
mergesort(a, b, start, halfpoint);
mergesort(a, b, halfpoint + 1, end);
merge(a, b, start, halfpoint, end);
}
}
void merge(int *a, int *b, int start, int halfpoint, int end) {
int h, i, j, k;
h = start;
i = start;
j = halfpoint + 1;
while ((h <= halfpoint) && (j <= end)) {
if (a[h] <= a[j]) {
b[i] = a[h];
h++;
} else {
b[i] = a[j];
j++;
}
i++;
}
if (h > halfpoint) {
for (k = j; k <= end; k++) {
b[i] = a[k];
i++;
}
} else {
for (k = h; k <= halfpoint; k++) {
b[i] = a[k];
i++;
}
}
// Write the final sorted array to our original one
for (k = start; k <= end; k++) {
a[k] = b[k];
}
}
int main(int argc, char** argv) {
int num;
cout << "How many numbers do you want to sort: ";
cin >> num;
int a[num];
int b[num];
for (int i = 0; i < num; i++) {
cout << (i + 1) << ": ";
cin >> a[i];
}
// Start merge sort
mergesort(a, b, 0, num - 1);
// Print the sorted array
cout << endl;
for (int i = 0; i < num; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
配列だけを使用して実装する方法を次に示します。
#include <iostream>
using namespace std;
//The merge function
void merge(int a[], int startIndex, int endIndex)
{
int size = (endIndex - startIndex) + 1;
int *b = new int [size]();
int i = startIndex;
int mid = (startIndex + endIndex)/2;
int k = 0;
int j = mid + 1;
while (k < size)
{
if((i<=mid) && (a[i] < a[j]))
{
b[k++] = a[i++];
}
else
{
b[k++] = a[j++];
}
}
for(k=0; k < size; k++)
{
a[startIndex+k] = b[k];
}
delete []b;
}
//The recursive merge sort function
void merge_sort(int iArray[], int startIndex, int endIndex)
{
int midIndex;
//Check for base case
if (startIndex >= endIndex)
{
return;
}
//First, divide in half
midIndex = (startIndex + endIndex)/2;
//First recursive call
merge_sort(iArray, startIndex, midIndex);
//Second recursive call
merge_sort(iArray, midIndex+1, endIndex);
merge(iArray, startIndex, endIndex);
}
//The main function
int main(int argc, char *argv[])
{
int iArray[10] = {2,5,6,4,7,2,8,3,9,10};
merge_sort(iArray, 0, 9);
//Print the sorted array
for(int i=0; i < 10; i++)
{
cout << iArray[i] << endl;
}
return 0;
}
この質問はすでに回答されていることは承知していますが、2 セント追加することにしました。以下は、マージ操作で追加のスペースのみを使用するマージ ソートのコードです (追加のスペースは、スタックがポップされると破棄される一時的なスペースです)。実際、このコードでは、ヒープ操作が使用されていない (new
どこにも宣言されていない) ことがわかります。
お役に立てれば。
void merge(int *arr, int size1, int size2) {
int temp[size1+size2];
int ptr1=0, ptr2=0;
int *arr1 = arr, *arr2 = arr+size1;
while (ptr1+ptr2 < size1+size2) {
if (ptr1 < size1 && arr1[ptr1] <= arr2[ptr2] || ptr1 < size1 && ptr2 >= size2)
temp[ptr1+ptr2] = arr1[ptr1++];
if (ptr2 < size2 && arr2[ptr2] < arr1[ptr1] || ptr2 < size2 && ptr1 >= size1)
temp[ptr1+ptr2] = arr2[ptr2++];
}
for (int i=0; i < size1+size2; i++)
arr[i] = temp[i];
}
void mergeSort(int *arr, int size) {
if (size == 1)
return;
int size1 = size/2, size2 = size-size1;
mergeSort(arr, size1);
mergeSort(arr+size1, size2);
merge(arr, size1, size2);
}
int main(int argc, char** argv) {
int num;
cout << "How many numbers do you want to sort: ";
cin >> num;
int a[num];
for (int i = 0; i < num; i++) {
cout << (i + 1) << ": ";
cin >> a[i];
}
// Start merge sort
mergeSort(a, num);
// Print the sorted array
cout << endl;
for (int i = 0; i < num; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
これは簡単に理解できます。
#include <iostream>
using namespace std;
void Merge(int *a, int *L, int *R, int p, int q)
{
int i, j=0, k=0;
for(i=0; i<p+q; i++)
{
if(j==p) //When array L is empty
{
*(a+i) = *(R+k);
k++;
}
else if(k==q) //When array R is empty
{
*(a+i) = *(L+j);
j++;
}
else if(*(L+j) < *(R+k)) //When element in L is smaller than element in R
{
*(a+i) = *(L+j);
j++;
}
else //When element in R is smaller or equal to element in L
{
*(a+i) = *(R+k);
k++;
}
}
}
void MergeSort(int *a, int len)
{
int i, j;
if(len > 1)
{
int p = len/2 + len%2; //length of first array
int q = len/2; //length of second array
int L[p]; //first array
int R[q]; //second array
for(i=0; i<p; i++)
{
L[i] = *(a+i); //inserting elements in first array
}
for(i=0; i<q; i++)
{
R[i] = *(a+p+i); //inserting elements in second array
}
MergeSort(&L[0], p);
MergeSort(&R[0], q);
Merge(a, &L[0], &R[0], p, q); //Merge arrays L and R into A
}
else
{
return; //if array only have one element just return
}
}
int main()
{
int i, n;
int a[100000];
cout<<"Enter numbers to sort. When you are done, enter -1\n";
i=0;
while(true)
{
cin>>n;
if(n==-1)
{
break;
}
else
{
a[i] = n;
i++;
}
}
int len = i;
MergeSort(&a[0], len);
for(i=0; i<len; i++)
{
cout<<a[i]<<" ";
}
return 0;
}