ページ 11

ソートに関する質問

Posted: 2017年11月26日(日) 21:30
by peko
プログラミング初心者です。
i=1番目から見ていき、a=0の値が出たとき、
その0を一番後ろにずらすプログラムを作りたいのですが、どのようにすればよいか分かりません。

0,2,20,14,0,5,3,1,19,0,4,6,10,0,7,15,11,16,0,8
↓ソート後
0,2,20,14,5,3,1,19,4,6,10,7,15,11,16,8,0,0,0,0

よろしくお願いいたします。

コード:

#include<stdio.h>
int main (void){
	int a[20]={0,2,20,14,0,5,3,1,19,0,4,6,10,0,7,15,11,16,0,8};
	int i;
	
	for(i=0;i<20;i++){
		printf("%d-",a[i]);
	}
	
	for(i=1;i<20;i++){
		
	}

	return 0;
}


Re: ソートに関する質問

Posted: 2017年11月27日(月) 00:56
by かずま
peko さんが書きました: i=1番目から見ていき、a=0の値が出たとき、
その0を一番後ろにずらすプログラムを作りたいのですが、どのようにすればよいか分かりません。

0 でないものを前にずらし、
後ろは 0 で埋めると考えてみましょう。

コード:

    j = 1;
    for (i = 1; i < 20; i++)
	    if (a[i] が 0 でなければ)
			a[i] を a[j] にコピーし、j を進める
	while (j が 20 より小さければ)
		a[j] に 0 を入れ、j を進める
これを参考にしてプログラムを完成させ、
それを提示してから解決にしましょう。

Re: ソートに関する質問

Posted: 2017年11月27日(月) 14:16
by peko
 ヒントありがとうございました。うまく動きました。
念のため正しいか、確認していただけるとありがたいです。

コード:

#include<stdio.h>
int main (void){
	int a[20]={0,2,20,14,12,5,3,1,19,0,4,6,10,0,7,15,11,16,0,8};
	int i,j;
	//int b[20]={0};

	for(i=0;i<20;i++){
		printf("%d-",a[i]);
	}
printf("\n");

	j=1;
	for(i=1;i<20;i++){
		if(a[i]!=0){
			a[j]=a[i];
			printf("%d-",a[j]);
			j++;
		}
	}
	while(j<20){
		a[j]=0;
		j++;
	}



printf("\n");
	for(i=0;i<20;i++){
		printf("%d-",a[i]);
	}

	return 0;
}

Re: ソートに関する質問

Posted: 2017年11月28日(火) 16:30
by peko
追加で質問です。

重複した値を0にし、後ろに0を付け加えることはできたのですが、40以上の値が2つ出てきたときに、2個目の値を0にして、
後ろに加えることが出来ません。
どのように変更すればよろしいでしょうか?
よろしくお願いします。

例)-40-5-3-1-16-0-44- -0-8
ソート後
-40-5-3-1-16-6- 8-0-0-0

コード:

int main (void){
    int a[20]={0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,10,16,0,8};
    int i,j;
    int b[20]={0};

    for(i=0;i<20;i++){
        printf("%d-",a[i]);
    }
printf("\n");

	for(i=0;i<20;i++){
		b[i]=a[i];
		if(a[i]!=0){
			for(j=0;j<i;j++){
				if(a[i]==b[j]){
					a[i]=0;
				}
			}
		}
	}

    j=1;
    for(i=1;i<20;i++){
        if(a[i]!=0){
            a[j]=a[i];
            printf("%d-",a[j]);
            j++;
        }
    }
    while(j<20){
        a[j]=0;
        j++;
    }



printf("\n");
    for(i=0;i<20;i++){
        printf("%d-",a[i]);        //並び替えた結果
    }




    return 0;
}

Re: ソートに関する質問

Posted: 2017年11月28日(火) 21:13
by かずま
peko さんが書きました: 重複した値を0にし、後ろに0を付け加えることはできたのですが、40以上の値が2つ出てきたときに、2個目の値を0にして、
後ろに加えることが出来ません。
どのように変更すればよろしいでしょうか?
int a[20]={0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,10,16,0,8};

これはどうなってほしいんですか?
16 が重複しています。0 も 44 も重複しています。
40以上の値が 3個あります。

Re: ソートに関する質問

Posted: 2017年11月28日(火) 22:55
by peko
int a[20]={0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,10,16,0,8};
ソート後
int a[20]={0,2,20,14,40,5,3,1,16,6,10,7,15,10,8,0,0,0,0};


重複した値、16 40以上の値2つ目 44 

この2つを一度0にした後、a[1]から見ていき全ての0を配列の一番後ろにまとめたいのですが、、、
現状のコードでは、 16 の処理はうまくできたのですが、 44 に対する処理がどうすればよいかわからない状態です。

ご指導お願いします。

Re: ソートに関する質問

Posted: 2017年11月29日(水) 00:16
by かずま
peko さんが書きました:int a[20]={0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,10,16,0,8};
ソート後
int a[20]={0,2,20,14,40,5,3,1,16,6,10,7,15,10,8,0,0,0,0};
ソート後の個数が 19 になっていますよ。

すみません。質問の値が間違っていました。
44 が 2つ。すなわち、40以上の値が 3個ある場合
について質問しているつもりでした。

int a[20]={0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,44,16,0,8};

重複または 40以上の値が 3個ある場合、
2個目だけを 0 に変え、3個目は残すんですか?
それとも、3個目も 0 に変えるんですか?

また、0 に変えるといっても、
その変えた 0 は最後に持っていくんだから、
単に 2個目以降の重複したものを削除し、
後ろに 0 を追加する、でいいのですか?

次のプログラムでいいんでしょうか?

コード:

#include <stdio.h>

int main(void)
{
    int a[20] = {0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,44,16,0,8};
    int i, j, k;
    int has40 = 0;
 
    for (i = 0; i < 20; i++)
        printf(i ? ",%d" : "%d", a[i]);
    putchar('\n');
 
    for (j = i = 1; i < 20; i++) {
        int copy = 1;
        if (a[i] == 0) copy = 0; // 0 はコピーしない
        if (a[i] >= 40) {
            if (has40) copy = 0; // 40以上は既にあるのでコピーしない
            has40 = 1; // 40以上があった
        }
        else {
            for (k = 0; k < i; k++)
                if (a[i] == a[k]) break;
            if (k < i) copy = 0; // 重複はコピーしない
        }
        if (copy) a[j++] = a[i]; // コピーする
    }
    while (j < 20)
        a[j++] = 0;

    for (i = 0; i < 20; i++)
        printf(i ? ",%d" : "%d", a[i]);        //並び替えた結果
    putchar('\n');

    return 0;
}
実行結果

コード:

0,2,20,14,40,5,3,1,16,0,44,6,10,0,7,15,44,16,0,8
0,2,20,14,40,5,3,1,16,6,10,7,15,8,0,0,0,0,0,0
continue を使うと copyフラグが要らなくなるんですが、
continue を使わないほうが初級者にはわかりやすい
と思って、このようにしました。

Re: ソートに関する質問

Posted: 2017年11月29日(水) 00:22
by かずま
かずま さんが書きました:

コード:

        if (a[i] >= 40) {
次のように修正します。

コード:

        else if (a[i] >= 40) {

Re: ソートに関する質問

Posted: 2017年11月29日(水) 13:02
by peko
合っています!
ご回答ありがとうございました。

Re: ソートに関する質問

Posted: 2017年11月29日(水) 17:02
by かずま
peko さんが書きました:合っています!
もらったコードが動いたので、それだけで解決ですか?
コードの意味はちゃんと理解しましたか?

・後で追加した else にはどういう意味があるのか説明できますか?
・copyフラグを使わずに continue を使うコードが書けますか?
・has40フラグを使わなくても、重複のチェックと同様に、既に
 40以上の値があったかどうか調べるやり方を書けますか?
・a[j] = a; j++; を a[j++] = a; と書けることに
 気づきましたか?