質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1186閲覧

C++ マージソートについて

yone_

総合スコア13

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/02/02 17:16

■マージソートのアルゴリズムについて
N個の整数乱数(1以上100以下の整数)を発生させ配列Merge〔〕に格納し、マージソートによりソートするプログラムを組みたいのですが、出力が上手くソートされません。

プログラム内の★1と★2で区切ったあたりに問題があると思うのですが、どうも気づけません。
正しくソートし出力するにはどこを修正すればよいのでしょうか?
よろしくお願いします。

■プログラム
include <stdio.h>
include <stdlib.h>
include <time.h>
define N 8

int Merge[N], tmpmerge[N];

void merge_two(int fr1, int to1,int fr2, int to2)
{
int i, sw1, sw2, tmp1, tmp2;

sw1=0; sw2=0; tmp1=fr1; tmp2=fr2; for(i=fr1; i<to2; i++){tmpmerge[i] = Merge[i];}

★1
int j;
double tmpmerge = Merge[i];
for (j = i-1; j>fr1 && tmpmerge < Merge[j]; j--){
Merge[j+1] = Merge[j];
}
printf("\n");
printf("fr1=%d , to1=%d , fr2=%d , to2=%d\n" , fr1 , to1 , fr2 , to2);
for(j=0; j<8; j++){
printf("%d ",Merge[j]);
}
★1
}

void mergesort(int first, int last)
{
if (first < last) {
mergesort(first, (first+last)/2);
mergesort((first+last)/2+1, last);
merge_two(first, (first+last)/2, (first+last)/2+1, last);
}
}
★2
int main() {
int i , ransu;
srand((unsigned int)time(NULL));
for(i=0; i<8; i++)
{
ransu=rand()%100 + 1;

Merge[i] = ransu;
}
printf("Numbers: ");
for(i=0; i<8; i++){
printf("%d ",Merge[i]);
if(i%10==9){
printf("¥n");
}
}
★2
mergesort(0,N-1);

}

■出力結果
Numbers: 89 70 4 73 93 19 32 69
fr1=0 , to1=0 , fr2=1 , to2=1
89 70 4 73 93 19 32 69
fr1=2 , to1=2 , fr2=3 , to2=3
89 70 4 73 93 19 32 69
fr1=0 , to1=1 , fr2=2 , to2=3
89 70 4 73 93 19 32 69
fr1=4 , to1=4 , fr2=5 , to2=5
89 70 4 73 93 19 32 69
fr1=6 , to1=6 , fr2=7 , to2=7
89 70 4 73 93 19 32 69
fr1=4 , to1=5 , fr2=6 , to2=7
89 70 4 73 93 19 32 69
fr1=0 , to1=3 , fr2=4 , to2=7
89 70 4 73 93 19 32 69

↑すべてソートされず同じ並びになってしまいます…

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2019/02/03 00:14

...これ、マージソートになってんですかね? 分割/併合はそれぞれドコでやってんですか?
guest

回答2

0

回答ではないですが、

CやC++のコードを書くなら、VisualStudioやEclipseなど、ソースデバッグできる環境を用意しましょう。
任意のソースの行でブレークポイントを設定して各変数の値を見ることができます。
また、1行づつ実行して変数の変化を見ることができるようになります

投稿2019/02/02 23:48

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

推奨されていない質問(デバッグしてください)のような気もしますが、、、

ちょっと追ってみました。 (デバッガ以前の問題ですね、、、)
「質問への追記・修正」にもありますが、マージソートになって無いみたいですね。
アルゴリズムと実際のコードを対比してみてください。
多分、 merge_two()で行おうとしていると思いますが、ざっと見た限りでも、以下の不明点。 (merge_two()内)

  1. double tmpmerge = Merge[i]; i の値がto2 になっています。良い?
  2. ここで宣言されているtmpmergeは、グローバルの tmpmerge[N] と被っています。意図したもの?
  3. 次の for()文、Merge[] をそのまま、書き換えています。これは入替えでもなく、壊しています。
  4. 先ほどの tmpmerge (ローカル&グローバル共に) 値が代入されていますが、使われていません。

ちょっとした手直しでは無理。コメントを入れつつ、元のアルゴリズムと比べてみてください。

[作ってみた]
Wiki-pediaにあった記述を元に merge_two()を書き換えてみました。
引数は、first: ソート対象の先頭、mid: ソート対象の中間位置、tail: 最終位置+1
呼び出す方も併せて変更。

C

1void merge_two(int first, int mid, int tail) 2{ 3 int i = first; // 前半部分の読み出し位置 4 int j = mid; // 後半部分の読み出し位置 5 int k = 0; // ソート結果の書き出し位置 6 i = first; j = mid; k = 0; 7 while ((i < mid) && (j < tail)) { // 前半/後半のデータがある場合 8 if (Merge[i] < Merge[j]) tmpmerge[k++] = Merge[i++]; 9 else tmpmerge[k++] = Merge[j++]; 10 } 11 while (i < mid) tmpmerge[k++] = Merge[i++]; // 前半部分が残った場合のみ 12 while (j < tail) tmpmerge[k++] = Merge[j++]; // 後半部分が残った場合のみ 13 i = first; k = 0; 14 while (i < tail) Merge[i++] = tmpmerge[k++]; // Merge[]配列に書き戻し 15}

元コードと様相は変わってしまいましたが、参考までに。

投稿2019/02/03 12:47

編集2019/02/03 15:18
pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問