C语言对数组元素进行冒泡排序的实现

在实际开发中,有很多场景需要我们将数组元素按照从大到小(或者从小到大)的顺序排列,这样在查阅数据时会更加直观,例如:

  • 一个保存了班级学号的数组,排序后更容易分区好学生和坏学生;
  • 一个保存了商品单价的数组,排序后更容易看出它们的性价比。

对数组元素进行排序的方法有很多种,比如冒泡排序、归并排序、选择排序、插入排序、快速排序等,其中最经典最需要掌握的是「冒泡排序」。

以从小到大排序为例,冒泡排序的整体思想是这样的:

  • 从数组头部开始,不断比较相邻的两个元素的大小,让较大的元素逐渐往后移动(交换两个元素的值),直到数组的末尾。经过第一轮的比较,就可以找到最大的元素,并将它移动到最后一个位置。
  • 第一轮结束后,继续第二轮。仍然从数组头部开始比较,让较大的元素逐渐往后移动,直到数组的倒数第二个元素为止。经过第二轮的比较,就可以找到次大的元素,并将它放到倒数第二个位置。
  • 以此类推,进行 n-1(n 为数组长度)轮“冒泡”后,就可以将所有的元素都排列好。

整个排序过程就好像气泡不断从水里冒出来,最大的先出来,次大的第二出来,最小的最后出来,所以将这种排序方式称为冒泡排序(Bubble Sort)。

下面我们以“3  2  4  1”为例对冒泡排序进行说明。

第一轮  排序过程
3  2  4  1    (最初)
2  3  4  1    (比较3和2,交换)
2  3  4  1    (比较3和4,不交换)
2  3  1  4    (比较4和1,交换)
第一轮结束,最大的数字 4 已经在最后面,因此第二轮排序只需要对前面三个数进行比较。

第二轮  排序过程
2  3  1  4 (第一轮排序结果)
2  3  1  4 (比较2和3,不交换)
2  1  3  4 (比较3和1,交换)
第二轮结束,次大的数字 3 已经排在倒数第二个位置,所以第三轮只需要比较前两个元素。

第三轮  排序过程
2  1  3  4  (第二轮排序结果)
1  2  3  4  (比较2和1,交换)

至此,排序结束。

算法总结及实现

对拥有 n 个元素的数组 R[n] 进行 n-1 轮比较。

第一轮,逐个比较 (R[1], R[2]),  (R[2], R[3]),  (R[3], R[4]),  …….  (R[N-1], R[N]),最大的元素被移动到 R[n] 上。

第二轮,逐个比较 (R[1], R[2]),  (R[2], R[3]),  (R[3], R[4]),  …….  (R[N-2], R[N-1]),次大的元素被移动到 R[n-1] 上。
。。。。。。
以此类推,直到整个数组从小到大排序。

具体的代码实现如下所示:

#include <stdio.h>
int main(){
  int nums[10] = {4, 5, 2, 10, 7, 1, 8, 3, 6, 9};
  int i, j, temp;
  //冒泡排序算法:进行 n-1 轮比较
  for(i=0; i<10-1; i++){
    //每一轮比较前 n-1-i 个,也就是说,已经排序好的最后 i 个不用比较
    for(j=0; j<10-1-i; j++){
      if(nums[j] > nums[j+1]){
        temp = nums[j];
        nums[j] = nums[j+1];
        nums[j+1] = temp;
      }
    }
  }

  //输出排序后的数组
  for(i=0; i<10; i++){
    printf("%d ", nums[i]);
  }
  printf("\n");

  return 0;
}

运行结果:
1 2 3 4 5 6 7 8 9 10

优化算法

上面的算法是大部分教材中提供的算法,其中有一点是可以优化的:当比较到第 i 轮的时候,如果剩下的元素已经排序好了,那么就不用再继续比较了,跳出循环即可,这样就减少了比较的次数,提高了执行效率。

未经优化的算法一定会进行 n-1 轮比较,经过优化的算法最多进行 n-1 轮比较,高下立判。

优化后的算法实现如下所示:

#include <stdio.h>
int main(){
  int nums[10] = {4, 5, 2, 10, 7, 1, 8, 3, 6, 9};
  int i, j, temp, isSorted;

  //优化算法:最多进行 n-1 轮比较
  for(i=0; i<10-1; i++){
    isSorted = 1; //假设剩下的元素已经排序好了
    for(j=0; j<10-1-i; j++){
      if(nums[j] > nums[j+1]){
        temp = nums[j];
        nums[j] = nums[j+1];
        nums[j+1] = temp;
        isSorted = 0; //一旦需要交换数组元素,就说明剩下的元素没有排序好
      }
    }
    if(isSorted) break; //如果没有发生交换,说明剩下的元素已经排序好了
  }
  for(i=0; i<10; i++){
    printf("%d ", nums[i]);
  }
  printf("\n");

  return 0;
}

我们额外设置了一个变量 isSorted,用它作为标志,值为“真”表示剩下的元素已经排序好了,值为“假”表示剩下的元素还未排序好。

每一轮比较之前,我们预先假设剩下的元素已经排序好了,并将 isSorted 设置为“真”,一旦在比较过程中需要交换元素,就说明假设是错的,剩下的元素没有排序好,于是将 isSorted 的值更改为“假”。

每一轮循环结束后,通过检测 isSorted 的值就知道剩下的元素是否排序好。

到此这篇关于C语言对数组元素进行冒泡排序的实现的文章就介绍到这了,更多相关C语言数组冒泡排序内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言将数组中元素的数排序输出的相关问题解决

    问题描述:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个.例如输入数组{32,  321},则输出这两个能排成的最小数字32132.请给出解决问题的算法,并证明该算法.       思路:先将整数数组转为字符串数组,然后字符串数组进行排序,最后依次输出字符串数组即可.这里注意的是字符串的比较函数需要重新定义,不是比较a和b,而是比较ab与 ba.如果ab < ba,则a < b:如果ab > ba,则a > b:如果ab = ba,则a = b.比较

  • c语言合并两个已排序数组的示例(c语言数组排序)

    问题:将两个已排序数组合并成一个排序数组 这里先不考虑大数据量的情况(在数据量很大时不知大家有什么好的思路或方法?),只做简单数组的处理. 简单代码如下: 说明:之所以把merge函数定义成返回数组长度,是因为后续会有重复数据合并功能的merge版本,考虑到接口一致性. 复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <string.h> int merge(int* ar1, int len1, int

  • C语言对数组元素进行冒泡排序的实现

    在实际开发中,有很多场景需要我们将数组元素按照从大到小(或者从小到大)的顺序排列,这样在查阅数据时会更加直观,例如: 一个保存了班级学号的数组,排序后更容易分区好学生和坏学生: 一个保存了商品单价的数组,排序后更容易看出它们的性价比. 对数组元素进行排序的方法有很多种,比如冒泡排序.归并排序.选择排序.插入排序.快速排序等,其中最经典最需要掌握的是「冒泡排序」. 以从小到大排序为例,冒泡排序的整体思想是这样的: 从数组头部开始,不断比较相邻的两个元素的大小,让较大的元素逐渐往后移动(交换两个元素

  • 浅谈C语言数组元素下标为何从0开始

    很多同学可能在学习数组时会有这个疑问,下标为什么不从1开始呢?从1开始不是更符合大家的日常习惯吗?生活中我们通常说第1个,而不是第0个.的确,有些计算机语言如早期的Pascal语言,数组元素的下标是从1开始的.难道是C语言故意要与众不同?要弄清楚这个问题,得先看一下计算机底层是怎样处理数组元素的.我们先编写了一个小程序,然后在visual studio中对其进行了反汇编.源程序和反汇编后的部分代码如下: 源程序: int arr[5];  //一个全局数组 int main() {    int

  • C语言算法练习之数组元素排序

    目录 一.问题描述 二.算法实例编译环境 三.算法实例实现过程 3.1.包含头文件 3.2.定义宏和声明数组 3.3.声明相关变量 3.4.随机生成十个数字赋值给数组 3.5.输出随机生成的十个数字 3.6.数组从小到大进行排序 3.7.输出数组元素排序好的数字 四.经典算法实例程序 完整代码 4.1.main.h文件 4.2.main.c文件 五.总结 一.问题描述 求数组的排序 问题的描述 如下几点所示 使用rand()库函数随机生成10个1-100之间的数字. 声明数组的大小为10. 随机

  • C语言数组元素的循环移位方法

    如下所示: /*C语言数组元素的循环移位*/ #include <stdio.h> int main() { int num[5],num1[5]; int i, j,k=1; int t,n; printf("请输入5个数:"); for(i=0;i<5;i++) { scanf("%d",&num[i]); //将数读入数组num } printf("请输入循环次数:"); scanf("%d",

  • 解决C语言数组元素循环右移的问题

    如下所示: #include<stdio.h> #define N 100 int main() { int a[N]; int i,j,k,n,m,temp=0; scanf("%d %d",&n,&m); i=0; while(i<n) { scanf("%d",&a[i]); i++; } for(j=0;j<m;j++) //移动次数 { temp=a[n-1]; //保存最后一位数 for(k=n-1;k&g

  • C语言数组元素循环右移问题及解决方法

    C 语言是一种通用的.面向过程式的计算机程序设计语言.1972 年,为了移植与开发 UNIX 操作系统,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言. C 语言是一种广泛使用的计算机语言,它与 Java 编程语言一样普及,二者在现代软件程序员之间都得到广泛使用. 题目内容: 解题思路 方法一: 这是我自己摸索出来的一种方法,通过对数组的多次逆置来达到循环的效果,一共对数组进行了三次逆置,所以就需要构造一个函数, 这个函数既可以逆置一个数组,也可以逆置数组的部分区间. 1,先将整个数组[0,N

  • go语言题解LeetCode453最小操作次数使数组元素相等

    目录 题目描述 思路分析 AC 代码 小结 遍历数组一次 解题思路 代码 强行找规律 解题思路 代码 题目描述 原题链接 : 453. 最小操作次数使数组元素相等 - 力扣(LeetCode) (leetcode-cn.com) 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 .返回让数组所有元素相等的最小操作次数. 示例 1: 输入:nums = [1,2,3] 输出:3 解释: 只需要3次操作(注意每次操作会增加两个元素的值): [1,2,3] => [2,3,3

  • C语言 array数组的用法详解

    目录 一维数组的创建与初始化 程序一: 程序二: 程序三 程序四(二维数组 - 二维数组 的 列 绝对不能 省略 ) 二维数组在内存中的存储 程序一 数组作为函数参数,怎么作? 实例:冒泡排序 数组名: 一维数组的创建与初始化 数组是一种相同类型元素的集合 程序一: #include<stdio.h> #include<string.h> int main() { 创建一个数组 int arr1[10];// [常量] 初始化 int arr[10]={1,2,3};不完全初始化,

  • C语言中数组的使用详解

    目录 1 数组的基本概念 2 数组定义语法 3 一维数组的初始化 3.1 全部初始化 3.2 部分元素赋初值 3.3 省略长度赋初值 4 一维数组的使用示例 4.1 求最大值.最小值.平均值 4.2 数组逆置 4.3 数组排序 4.3.1 冒泡排序 4.3.2 选择排序 选择列表中的最小值与未排序列表中的第一个值互换位置. 4.3.3 直接插入排序 5 二维数组 5.1 二维数组的概念 5.2 二维数组的初始化 5.2.1 全部初始化 按行全部赋初值 5.2.2 部分初始化 5.2.3 省略长度

随机推荐