PTA 编程题(C语言)-- 简化的插入排序

题目标题:简化的插入排序       题目作者:C课程组 浙江大学

本题要求编写程序,将一个给定的整数插到原本有序的整数序列中,使结果序列仍然有序。

输入格式:

输入在第一行先给出非负整数N(<10);第二行给出N个从小到大排好顺序的整数;第三行给出一个整数X。

输出格式:

在一行内输出将X插入后仍然从小到大有序的整数序列,每个数字后面有一个空格。

输入样例:

5
1 2 4 5 7
3

输出样例:

1 2 3 4 5 7 

思路1:(1)输入整数到变量N;声明一个数组A[N](有些古早的编译器不允许在程序中用变量做为数组的长度来声明数组,这里也可同一声明为A[10]),把第二行的N个数一次读入到数组A中;输入要插入的整数到变量X。

(2)遍历数组的每个元素A[i],如果X < A[i],就先输出X,再输出A[i];否则就直接输出A[i]。这里注意,如果执行某一次循环体时,已经将X输出了,那么后面的循环体就不用再输出X了。这里有一个小技巧,用flag=1标记X尚未输出,flag=0标记X已经输出。

代码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)每次执行循环体都要判断一下flag的值。

思路2:(1)输入整数到变量N;声明一个数组A[N](有些古早的编译器不允许在程序中用变量做为数组的长度来声明数组,这里也可同一声明为A[10]),把第二行的N个数一次读入到数组A中;输入要插入的整数到变量X。给变量flag赋值为N,这里的N用来标记要插入的位置。

(2)遍历数组的每个元素A[i],如果 A[i] < x,就输出A[i];否则标记flag=i,并跳出循环。接着输出一个X。再接着从A[flag]开始输出剩余的数组A中的元素。

代码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;
}

代码2相较于代码1的优点是减少了if内条件判断的次数。

代码1和代码2,都没有改变原数组的结构。这对新手比较友好。但是有的时候我们需要通过改变数组的结构来完成一定的功能。下面就给出这样一种解法。

思路3:(1)输入整数到变量N;声明一个数组A[N+1](有些古早的编译器不允许在程序中用变量做为数组的长度来声明数组,这里也可同一声明为A[10]),把第二行的N个数一次读入到数组A中;输入要插入的整数到变量X。给变量flag赋值为N,这里的N用来标记要插入的位置。

(2)遍历数组的每个元素A[i],当遇到第一个i,使得 x<A[i] ,标记flag=i,并跳出循环。

(3)让i从N开始,把A[i-1]赋值给A[i],直到i=flag。执行完这一步,想让与让数组从下标为flag的元素开始整体向右游动一位。

(4)把X赋值给A[flag],这时就完成了插入。

代码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这种办法的一个好处就是,很容易在外面套一层循环,把它扩展成一种排序算法--插入排序。

思路4:还有一种方法就是,声明数组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;
}
更多PTA题目的的参考代码,可以在wx小程序里搜“PTA刷题助手”,或扫下面的二维码

猜你喜欢

转载自blog.csdn.net/morn_l/article/details/134061523
今日推荐