タイトル: 簡略化された挿入ソート タイトル 著者: C コース グループ 浙江大学
この質問では、元の順序の整数シーケンスに特定の整数を挿入して、結果のシーケンスが順序どおりになるようにするプログラムを作成する必要があります。
入力形式:
入力の最初の行では、負でない整数 N (<10) が与えられ、2 行目では昇順に並べられた N 個の整数が与えられ、3 行目では整数 X が与えられます。
出力フォーマット:
X を挿入した後も小さい値から大きい値の順に並べられた一連の整数を 1 行で出力します。各数値の後にスペースを入れます。
入力例:
5
1 2 4 5 7
3
出力サンプル:
1 2 3 4 5 7
アイデア 1: (1) 変数 N に整数を入力し、配列 A[N] を宣言します (一部の初期のコンパイラでは、プログラム内で配列を宣言するために配列の長さとして変数を使用することはできません。同じ宣言をここでも行うことができます) A[ 10] として)、2 行目の N 個の数値を配列 A に一度に読み取り、変数 X に挿入する整数を入力します。
(2) 配列の各要素 A[i] をトラバースします。X < A[i] の場合は、最初に X を出力し、次に A[i] を出力します。それ以外の場合は、A[i] を直接出力します。なお、あるループ本体の実行時にXが出力されていれば、それ以降のループ本体ではXを出力する必要はありません。ここにちょっとしたトリックがあります。X が出力されていないことを示すには flag=1 を使用し、X が出力されたことを示すには flag=0 を使用します。
コード 1:
#include <stdio.h>
int main () {
int N,X,i,flag=1;
int A[10];
scanf("%d", &N);
for (i = 0; i < N; i++) {
scanf("%d", &A[i]);
}
scanf("%d", &X);
for (i = 0; i < N; i++) {
if (flag && X < A[i]) {
printf("%d ", X);
flag = 0;
}
printf("%d ", A[i]);
}
if (flag) printf("%d ", X);
return 0;
}
ここでコード 1 の長所と短所について説明します。 (1) 配列 A の構造は変更せず、配列 A の要素を順番に出力する過程の適切なタイミングで X の出力を挿入します。 (2) ループ本体を実行するたびにフラグの値を判定する必要があります。
アイデア 2: (1) 変数 N に整数を入力し、配列 A[N] を宣言します (一部の初期のコンパイラでは、プログラム内で配列を宣言するために配列の長さとして変数を使用することはできません。同じ宣言をここでも行うことができます) A[ 10] として)、2 行目の N 個の数値を配列 A に一度に読み取り、変数 X に挿入する整数を入力します。値 N を変数 flag に割り当てます。N は、挿入される位置をマークするために使用されます。
(2) 配列の各要素 A[i] をトラバースし、A[i] < x の場合は A[i] を出力し、それ以外の場合は flag=i をマークしてループから抜け出します。次に、X を出力します。次に、配列 A の残りの要素を A[flag] から出力します。
コード 2:
#include <stdio.h>
int main () {
int N,X,i,flag;
int A[10];
scanf("%d", &N);
flag = N;
for (i = 0; i < N; i++) {
scanf("%d", &A[i]);
}
scanf("%d", &X);
for (i = 0; i < N; i++) {
if (A[i] < X) printf("%d ", A[i]);
else {
flag = i;
break;
}
}
printf("%d ", X);
for (i = flag; i < N; i++) printf("%d ", A[i]);
return 0;
}
コード 1 と比較したコード 2 の利点は、if 内の条件判断の数が減少することです。
コード 1 もコード 2 も、元の配列の構造を変更しません。これは初心者にとってよりフレンドリーです。ただし、特定の機能を完成させるために配列の構造を変更する必要がある場合があります。そのような解決策を以下に示します。
アイデア 3: (1) 変数 N に整数を入力し、配列 A[N+1] を宣言します (一部の初期のコンパイラでは、プログラム内で配列を宣言するために配列の長さとして変数を使用することはできません。同じ宣言を行うこともできます)。ここでは A[10] とします)、2 行目の N 個の数値を配列 A に一度に読み取り、変数 X に挿入する整数を入力します。値 N を変数 flag に割り当てます。N は、挿入される位置をマークするために使用されます。
(2) 配列の各要素 A[i] をたどって、x
(3) i を N から開始し、i=flag になるまで A[i-1] を A[i] に代入します。このステップを実行した後、配列を添字が flag である要素から開始して 1 つ右に移動する必要があります。
(4) A[flag]にXを代入して挿入完了です。
コード 3:
#include <stdio.h>
int main () {
int N,i,X,flag; // 用flag记录要插入的位置
scanf("%d", &N);
int A[N+1];
flag = N; // 默认插入最后
for (i = 0; i < N; i++) { // 输入原始数组
scanf("%d", &A[i]);
}
scanf("%d", &X); // 输入要插入的元素
for (i = 0; i < N; i++) {
if (X < A[i]) { // 第一个使得A[i]>X的位置i,就是要插入的位置
flag = i;
break;
}
}
for (i = N; i > flag; i--) { // 从要插入的位置之后所有元素向后移动一位
A[i] = A[i-1];
}
A[flag] = X; // 把新元素插入
for (i = 0; i < N+1; i++) { // 输出即可
printf("%d ", A[i]);
}
return 0;
}
コード 3 の方法の利点の 1 つは、外部にループを追加し、それをソート アルゴリズム挿入ソートに拡張するのが簡単であることです。
アイデア 4: もう 1 つの方法は、配列 A[N+1] を宣言し、挿入する数値 X を A[N] に代入し、配列 A に対して選択ソートまたはバブル ソートを実行することです。この方法は、にわとりを的中させて殺すことになるので、お勧めできません。
コード 4:
#include <stdio.h>
int main () {
int N,i,j,tmp;
int A[10];
scanf("%d\n", &N);
for (i = 0; i < N; i++) {
scanf("%d", &A[i]);
}
scanf("%d", &A[N]);
for (i = 0; i < N; i++) { // 选择排序
for (j = i+1; j < N+1; j++) {
if (A[i] > A[j]) {
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
}
// for (i = 0; i < N; i++) { // 冒泡排序
// for (j = 0; j < N-i; j++) {
// if (A[j] > A[j+1]) {
// tmp = A[j];
// A[j] = A[j+1];
// A[j+1] = tmp;
// }
// }
// }
for (i = 0; i < N+1; i++) {
printf("%d ", A[i]);
}
return 0;
}