C语言程序设计题|有序数组插入数字冒泡排序

C语言程序设计题|有序数组插入数字冒泡排序

题目

有一个已经排好序的数组 a[11] = {1,5,6,7,13,22,27,37,38,45}(原有10个升序元素,预留1个位置)。

输入一个数,将数字放到数组末尾,再使用冒泡排序,实现整体升序,最后输出数组。

说明:题目本意是"找到位置插入";如果你要求用冒泡排序实现,思路是:先把数字放到数组最后,再对全部11个元素冒泡升序。

完整代码

c 复制代码
#include <stdio.h>
int main()
{
    int a[11] = {1,5,6,7,13,22,27,37,38,45};
    int num, i, j, temp;
    printf("请输入要插入的整数:");
    scanf("%d", &num);

    // 第一步:把输入的数放到数组最后一个位置
    a[10] = num;

    // 第二步:冒泡排序,对全部11个元素升序排列
    for(i = 0; i < 10; i++)
    {
        for(j = 0; j < 10 - i; j++)
        {
            if(a[j] > a[j+1])
            {
                temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
    }

    // 第三步:输出插入排序后的数组
    printf("处理后的有序数组:\n");
    for(i = 0; i < 11; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

代码逐行讲解(小白版)

下面把这段代码拆成几块,一块一块地看,看完你就能自己写出来了。

1. 头文件与变量声明

c 复制代码
#include <stdio.h>
int main()
{
    int a[11] = {1,5,6,7,13,22,27,37,38,45};
    int num, i, j, temp;
  • #include <stdio.h>:告诉编译器"我要用输入输出功能",printf 和 scanf 都来自这里。
  • int main():程序的入口,C 程序从 main 的第一行开始执行。
  • int a[11] = {...}:定义一个能装 11 个整数的数组,前 10 个位置填好了升序数字,第 11 个位置(下标 10)暂时是 0,留给新数字。
  • num 存用户输入的数,i、j 是循环计数器,temp 是交换两个数时的"临时中转站"。

小知识:C 语言数组下标从 0 开始,所以 11 个元素的下标是 0 ~ 10,最后一个就是 a[10]。

2. 读入要插入的数字

c 复制代码
    printf("请输入要插入的整数:");
    scanf("%d", &num);
  • printf 只是在屏幕上打印一句提示,不影响逻辑。
  • scanf("%d", &num) 从键盘读一个整数存进 num。注意 & 不能丢,它表示"把值放到这个变量的地址里"。

3. 把新数字放到数组末尾

c 复制代码
    a[10] = num;

这一步就是题目要求的"放到数组末尾"。此时数组变成 11 个元素,但顺序可能被打乱------比如输入 3,数组就是 1,5,6,7,13,22,27,37,38,45,3,3 明显不在正确位置。

4. 冒泡排序:把 11 个数重新排好

c 复制代码
    for(i = 0; i < 10; i++)
    {
        for(j = 0; j < 10 - i; j++)
        {
            if(a[j] > a[j+1])
            {
                temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
    }

冒泡排序的核心思想:相邻两个数比较,大的往后挪,一轮下来最大的数就"冒"到了最后。

  • 外层 i 控制"跑几轮"。11 个数最多需要 10 轮,所以 i < 10。
  • 内层 j 控制"这一轮比较到哪"。因为每跑完一轮,末尾就多一个已经排好的数,所以比较范围逐轮缩小:j < 10 - i。
  • if(a[j] > a[j+1]):如果前一个比后一个大,说明顺序反了,需要交换。
  • 交换三行是固定套路,必须借助 temp:
c 复制代码
temp = a[j];      // 先把 a[j] 存起来
a[j] = a[j+1];    // 把小的挪到前面
a[j+1] = temp;    // 把存起来的大的放到后面

为什么不能直接 a[j] = a[j+1]; a[j+1] = a[j];?因为第一句执行完,a[j] 原来的值就被覆盖了,第二句拿到的已经是新值,等于没换。所以必须用 temp 暂存。

5. 输出结果

c 复制代码
    printf("处理后的有序数组:\n");
    for(i = 0; i < 11; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
  • 循环 i 从 0 到 10,正好遍历 11 个元素。
  • printf("%d ", a[i]) 中 %d 是整数的占位符,后面跟一个空格,让数字之间分开。
  • 最后的 printf("\n") 换行,return 0 表示程序正常结束。

6. 跑一遍看看

假设输入 20:

步骤 数组内容
初始 1, 5, 6, 7, 13, 22, 27, 37, 38, 45, 0
放入末尾 1, 5, 6, 7, 13, 22, 27, 37, 38, 45, 20
冒泡排序后 1, 5, 6, 7, 13, 20, 22, 27, 37, 38, 45

输出:1 5 6 7 13 20 22 27 37 38 45

7. 几个新手常踩的坑

  • 数组越界 :a[11] 只有下标 0~10,写 a[11] 就越界了,可能崩溃或输出乱码。
  • 循环边界写错 :内层写成 j < 11 - i 会访问 a[11],同样越界;正确是 j < 10 - i。
  • 忘了 & :scanf("%d", num) 会读不到值甚至崩溃。
  • 交换不用 temp:两个数会变成一样,排序结果错误。
  • 只排 10 个元素 :如果循环写成 i < 9 或输出只到 i < 10,最后一个数就漏掉了。

8. 不用冒泡排序的解题思路

如果题目没有强制要求冒泡排序,其实这道题的本质是「有序数组插入 」,不需要把 11 个数重新排一遍。核心思路只有一句话:从后往前找位置,边找边把元素往后挪,找到空位就把新数字放进去。

思路拆解
  1. 确定起点 :原数组有 10 个有效元素,下标是 0 ~ 9,新数字最终要放到下标 10 的位置,所以从 i = 9 开始往前看。
  2. 比较并后移 :只要 a[i] 比 num 大,说明 num 应该排在它前面,于是把 a[i] 往后挪一位(a[i+1] = a[i]),然后 i-- 继续往前比。
  3. 找到空位 :当遇到一个不大于 num 的元素,或者 i 已经减到 -1(说明 num 比所有元素都小),循环结束,此时 a[i+1] 就是 num 该待的位置。
  4. 放入新数字 :执行 a[i+1] = num,插入完成,数组依然保持升序。
用图理解

#mermaid-svg-A4DYyQIuQ9lBOUhp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-A4DYyQIuQ9lBOUhp .error-icon{fill:#552222;}#mermaid-svg-A4DYyQIuQ9lBOUhp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-A4DYyQIuQ9lBOUhp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .marker.cross{stroke:#333333;}#mermaid-svg-A4DYyQIuQ9lBOUhp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-A4DYyQIuQ9lBOUhp p{margin:0;}#mermaid-svg-A4DYyQIuQ9lBOUhp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .cluster-label text{fill:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .cluster-label span{color:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .cluster-label span p{background-color:transparent;}#mermaid-svg-A4DYyQIuQ9lBOUhp .label text,#mermaid-svg-A4DYyQIuQ9lBOUhp span{fill:#333;color:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .node rect,#mermaid-svg-A4DYyQIuQ9lBOUhp .node circle,#mermaid-svg-A4DYyQIuQ9lBOUhp .node ellipse,#mermaid-svg-A4DYyQIuQ9lBOUhp .node polygon,#mermaid-svg-A4DYyQIuQ9lBOUhp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .rough-node .label text,#mermaid-svg-A4DYyQIuQ9lBOUhp .node .label text,#mermaid-svg-A4DYyQIuQ9lBOUhp .image-shape .label,#mermaid-svg-A4DYyQIuQ9lBOUhp .icon-shape .label{text-anchor:middle;}#mermaid-svg-A4DYyQIuQ9lBOUhp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .rough-node .label,#mermaid-svg-A4DYyQIuQ9lBOUhp .node .label,#mermaid-svg-A4DYyQIuQ9lBOUhp .image-shape .label,#mermaid-svg-A4DYyQIuQ9lBOUhp .icon-shape .label{text-align:center;}#mermaid-svg-A4DYyQIuQ9lBOUhp .node.clickable{cursor:pointer;}#mermaid-svg-A4DYyQIuQ9lBOUhp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .arrowheadPath{fill:#333333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-A4DYyQIuQ9lBOUhp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-A4DYyQIuQ9lBOUhp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-A4DYyQIuQ9lBOUhp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-A4DYyQIuQ9lBOUhp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .cluster text{fill:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp .cluster span{color:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-A4DYyQIuQ9lBOUhp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-A4DYyQIuQ9lBOUhp rect.text{fill:none;stroke-width:0;}#mermaid-svg-A4DYyQIuQ9lBOUhp .icon-shape,#mermaid-svg-A4DYyQIuQ9lBOUhp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-A4DYyQIuQ9lBOUhp .icon-shape p,#mermaid-svg-A4DYyQIuQ9lBOUhp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-A4DYyQIuQ9lBOUhp .icon-shape .label rect,#mermaid-svg-A4DYyQIuQ9lBOUhp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-A4DYyQIuQ9lBOUhp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-A4DYyQIuQ9lBOUhp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-A4DYyQIuQ9lBOUhp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
输入 num
i = 9(从最后一个有效元素开始)
i >= 0 且 ai > num ?
ai+1 = ai(元素后移一位)
i--
ai+1 = num(放入空位)
输出 11 个元素

举个例子

原数组 1,5,6,7,13,22,27,37,38,45,输入 20:

步骤 i 比较 动作 数组变化
1 9 45 > 20 45 后移 ...,38,45,45
2 8 38 > 20 38 后移 ...,37,38,45
3 7 37 > 20 37 后移 ...,27,37,38
4 6 27 > 20 27 后移 ...,22,27,37
5 5 22 > 20 22 后移 ...,13,22,27
6 4 13 > 20 不成立 停止 空位在下标 5
7 --- --- a[5] = 20 1,5,6,7,13,20,22,27,37,38,45

整个过程只比较了 6 次、移动了 5 次,比冒泡排序快得多。

为什么这样是对的

因为原数组已经有序 ,所有比 num 大的元素一定连续地排在数组尾部。把它们整体后移一位,中间自然就空出一个位置,而这个位置恰好满足「左边都不大于 num,右边都不小于 num」,插入后数组仍然有序。

需要注意的边界
  • num 比所有元素都小 :i 会一路减到 -1,循环因 i >= 0 不成立而退出,此时 a[0] = num,正确。
  • num 比所有元素都大 :第一次比较就不成立,a[10] = num,相当于直接放到末尾,也正确。
  • i >= 0 不能省 :少了它,当 num 最小时会访问 a[-1],属于越界,可能崩溃或产生乱码。
三种写法怎么选
写法 时间复杂度 适用场景
放到末尾 + 冒泡排序 O(n²) 题目明确要求练习排序
从后往前找位置插入 O(n) 有序数组插入的标准解法
找到位置后整体后移(先找再移) O(n) 思路更直观,但要多写一个循环

小结:这道题的关键不是「排序」,而是「插入」。只要抓住「数组有序」这个条件,就能把 O(n²) 的排序优化成 O(n) 的一趟扫描。

8. 更简洁的方案(推荐掌握)

题目要求用冒泡排序,时间复杂度是 O(n²)。但既然原数组已经有序,其实没必要全部重排------从后往前找位置,边找边后移,一趟就能搞定,时间复杂度 O(n)。

c 复制代码
#include <stdio.h>
int main()
{
    int a[11] = {1,5,6,7,13,22,27,37,38,45};
    int num, i;
    printf("请输入要插入的整数:");
    scanf("%d", &num);

    // 从最后一个元素开始,比 num 大的都往后挪一位
    i = 9;
    while(i >= 0 && a[i] > num)
    {
        a[i+1] = a[i];
        i--;
    }
    // 空出来的位置放 num
    a[i+1] = num;

    printf("处理后的有序数组:\n");
    for(i = 0; i < 11; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

核心就三行:

c 复制代码
while(i >= 0 && a[i] > num)   // 从后往前找第一个不大于 num 的位置
{
    a[i+1] = a[i];            // 比 num 大的元素整体后移一位
    i--;
}
a[i+1] = num;                 // 空位就是 num 该待的地方

对比一下两种写法:

对比项 冒泡排序版 插入版(本方案)
时间复杂度 O(n²) O(n)
比较次数 约 55 次 最多 10 次
移动次数 大量交换 最多 10 次后移
代码长度 较长 更短
适用场景 练习循环与交换 有序数组插入的标准解法

注意:while 里的 i >= 0 不能省。如果输入的数比所有元素都小(比如 0),i 会一路减到 -1,此时 a[i+1] 正好是 a[0],把 num 放在最前面,逻辑依然正确;但少了这个判断就会越界访问 a[-1]。

如果题目没有强制要求冒泡排序,这个写法更符合"有序数组插入"的本意,也更值得记住。

相关推荐
Pniubi26 分钟前
力扣73 矩阵置零
算法·leetcode·矩阵
布莱克60511 小时前
C++ 中 map 的 insert 与 emplace:key 已存在时会覆盖吗?
开发语言·数据结构·c++·算法·map
D e re k ZH14 小时前
C++ 系统学习手记:从语法细节到工程实践
开发语言·数据结构·c++·算法
石小石Orz14 小时前
AI 正在蚕食我们的编码能力
前端·后端·算法
Zwawa16 小时前
屏幕不止一种:OLED、LCD1602字符屏、TFT/IPS图形屏和串口屏怎么用,这与TTY和PTY又有什么关系
c语言·单片机·嵌入式
Fruiticecake16 小时前
C 程序员速通现代 C++(一):lambda、std::function、移动语义与智能指针
c语言·c++
田甲16 小时前
做一款 Type-C 母座读卡器:GL3224 双卡方案实测
c语言·开发语言
民乐团扒谱机16 小时前
【微实验】NSGA-II(非支配排序遗传算法)——解决多目标优化问题的“自然选择模拟器”
linux·人工智能·算法