摘要:排序是计算机的一种操作方法,其目的是将一组“无序”的记录序列调整为“有序”的记录序列,主要分为内部排序和外部排序。

排序

排序是计算机的一种操作方法,其目的是将一组“无序”的记录序列调整为“有序”的记录序列,主要分为内部排序和外部排序。

(1)冒泡排序(起泡排序)

冒泡排序(Bubble Sort),其基本思路是,对于一组要排序的元素列,依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面,如此继续,直到比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成。

优点:稳定;

缺点:慢,每次只能移动相邻两个数据。

假设要对含有n个数的序列进行升序排列,冒泡排序算法步骤是:

①从存放序列的数组中的第一个元素开始到最后一个元素,依次对相邻两数进行比较,若前者大后者小,则交换两数的位置;

②第①趟结束后,最大数就存放到数组的最后一个元素里了,然后从第一个元素开始到倒数第二个元素,依次对相邻两数进行比较,若前者大后者小,则交换两数的位置;

③重复步骤①n-1趟,每趟比前一趟少比较一次,即可完成所求。

1、任意读入10个整数,将其用冒泡法按升序排列后输出。

  1. #define n 10
  2.  
  3. void main()
  4. {
  5. int a[n],i,j,t;
  6. for(i=0;i<n;i++)
  7. scanf("%d",&a[i]);
  8. for(j=1;j<=n-1;j++) /*n个数处理n-1趟*/
  9. for(i=0;i<=n-1-j;i++) /*每趟比前一趟少比较一次*/
  10. if(a[i]>a[i+1])
  11. {
  12. t=a[i];
  13. a[i]=a[i+1];
  14. a[i+1]=t;
  15. }
  16. for(i=0;i<n;i++)
  17. printf("%d\n",a[i]);
  18. }

2、传统方法:

  1. #include <stdio.h>
  2.  
  3. void main()
  4. {
  5. int a[11],i,j,t;
  6. printf("Input 10 numbers:\n");
  7. for(i=1;i<11;i++)
  8. {
  9. scanf("%d",&a[i]);
  10. }
  11. printf("\n");
  12. for(j=1;j<=9;j++)
  13. for(i=1;i<=10-j;i++)
  14. if(a[i]>a[i+1])
  15. {
  16. t=a[i];
  17. a[i]=a[i+1];
  18. a[i+1]=t;
  19. }
  20. printf("The sorted numbers:\n");
  21. for(i=1;i<11;i++)
  22. printf("%d ",a[i]);
  23. }

(2)选择法排序

选择排序法是每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。基于此思想的算法主要有简单选择排序、树型选择排序和堆排序。

优点:移动数据的次数已知(n-1次);

缺点:比较次数多,不稳定。

选择法排序是相对好理解的排序算法。假设要对含有n个数的序列进行升序排列,算法步骤是:

①从数组存放的n个数中找出最小数的下标(算法见下面的“求最值”),然后将最小数与第1个数交换位置;

②除第1个数以外,再从其余n-1个数中找出最小数(即n个数中的次小数)的下标,将此数与第2个数交换位置;

③重复步骤①n-1趟,即可完成所求。

1、任意读入10个整数,将其用选择法按升序排列后输出。

  1. #include <stdio.h>
  2. #define n 10
  3.  
  4. void main()
  5. {
  6. int a[n],i,j,k,t;
  7. for(i=0;i<n;i++) scanf("%d",&a[i]);
  8. for(i=0;i<n-1;i++) /*处理n-1趟*/
  9. {
  10. k = i;
  11. /*总是假设此趟处理的第一个(即全部数的第i个)数最小,k记录其下标*/
  12. for(j=i+1;j<n;j++)
  13. if(a[j] < a[k])
  14. k = j;
  15. if (k != i)
  16. {
  17. t = a[i];
  18. a[i] = a[k];
  19. a[k] = t;
  20. }
  21. }
  22. for(i=0;i<n;i++)
  23. printf("%d\n",a[i]);
  24. }

2、传统方法:

  1. #include <stdio.h>
  2.  
  3. void main()
  4. { int a[11],i,j,k,x;
  5. printf("Input 10 numbers:\n");
  6. for(i=1;i<=10;i++)
  7. scanf("%d",&a[i]);
  8. printf("\n");
  9. for(i=1;i<=10;i++)
  10. { k=i;
  11. for(j=i+1;j<=10;j++)
  12. if(a[j]<a[k]) k=j;
  13. if(i!=k)
  14. {
  15. x=a[i];
  16. a[i]=a[k];
  17. a[k]=x;
  18. }
  19. }
  20. printf("The sorted numbers:\n");
  21. for(i=1;i<=10;i++)
  22. printf("%d ",a[i]);
  23. }

函数法:

  1. #include <stdio.h>
  2.  
  3. void sort(int array[],int n)
  4. { int i,j,k,t;
  5. for(i=0;i<n-1;i++)
  6. { k=i;
  7. for(j=i+1;j<n;j++)
  8. if(array[j]<array[k])
  9. k=j;
  10. if(k!=i)
  11. { t=array[i];
  12. array[i]=array[k];
  13. array[k]=t;
  14. }
  15. }
  16. }
  17.  
  18. main()
  19. { int a[10],i;
  20. for(i=0;i<10;i++)
  21. scanf("%d",&a[i]);
  22. sort(a,10);/*数组名作函数参数*/
  23. for(i=0;i<10;i++)
  24. printf("%d ",a[i]);
  25. printf("\n");
  26. }

(3)插入法排序

优点:稳定,快;

缺点:比较次数不一定,比较次数越多,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。

要想很好地掌握此算法,先请了解“有序序列的插入算法”,就是将某数据插入到一个有序序列后,该序列仍然有序。插入算法参见下面的“数组元素的插入”。

1、将任意读入的整数x插入一升序数列后,数列仍按升序排列。

  1. #include <stdio.h>
  2. #define n 10
  3.  
  4. void main()
  5. {
  6. int a[n]={-1,3,6,9,13,22,27,32,49},x,j,k; /*注意留一个空间给待插数*/
  7. scanf("%d",&x);
  8. if(x>a[n-2]) a[n-1]=x ; /*比最后一个数还大就往最后一个元素中存放*/
  9. else /*查找待插位置*/
  10. {j=0;
  11. while( j<=n-2 && x>a[j]) j++;
  12. /*从最后一个数开始直到待插位置上的数依次后移一位*/
  13. for(k=n-2; k>=j; k- -)
  14. a[k+1]=a[k];
  15. a[j]=x; /*插入待插数*/
  16. }
  17. for(j=0;j<=n-1;j++) printf("%d ",a[j]);
  18. }

插入法排序的要领就是每读入一个数立即插入到最终存放的数组中,每次插入都使得该数组有序。

2、任意读入10个整数,将其用插入法按降序排列后输出。

  1. #include <stdio.h>
  2.  
  3. #define n 10
  4. main()
  5. {int a[n],i,j,k,x;
  6. scanf("%d",&a[0]); /*读入第一个数,直接存到a[0]中*/
  7. for(j=1;j<n;j++) /*将第2至第10个数一一有序插入到数组a中*/
  8. {scanf("%d",&x);
  9. if(x<a[j-1]) a[j]=x;
  10. /*比原数列最后一个数还小就往最后一个元素之后存放新读的数*/
  11. else /*以下查找待插位置*/
  12. {i=0;
  13. while(x<a[i]&&i<=j-1) i++;
  14. /*以下for循环从原最后一个数开始直到待插位置上的数依次后移一位*/
  15. for(k=j-1;k>=i;k--) a[k+1]=a[k];
  16. a[i]=x; /*插入待插数*/
  17. }
  18. }
  19. for(i=0;i<n;i++)
  20. printf("%d\n",a[i]);
  21. }

(4)归并排序

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并,即将两个都升序(或降序)排列的数据序列合并成一个仍按原序排列的序列。

1、有一个含有6个数据的升序序列和一个含有4个数据的升序序列,将二者合并成一个含有10个数据的升序序列。

  1. #include <stdio.h>
  2. #define m 6
  3. #define n 4
  4.  
  5. void main()
  6. {
  7. int a[m]={-3,6,19,26,68,100} ,b[n]={8,10,12,22};
  8. int i,j,k,c[m+n];
  9. i=j=k=0;
  10. while(i<m && j<n) /*将a、b数组中的较小数依次存放到c数组中*/
  11. {if(a[i]<b[j]){c[k]=a[i]; i++;}
  12. else {c[k]=b[j]; j++;}
  13. k++; }
  14. while(i>=m && j<n) /*若a中数据全部存放完毕,将b中余下的数全部存放到c中*/
  15. {c[k]=b[j]; k++; j++;}
  16. while(j>=n && i<m) /*若b中数据全部存放完毕,将a中余下的数全部存放到c中*/
  17. {c[k]=a[i]; k++; i++;}
  18. for(i=0;i<m+n;i++) printf("%d ",c[i]);
  19. }

(5)字符数组:(逆序排列)如:<ABCDE-EDCBA>

1、把输入的字符串逆序排列,如输入ABCDE,输出为EDCBA

  1. #include <stdio.h>
  2. #include<string.h>
  3.  
  4. void main()
  5. { char c,str[80];
  6. int i,j;
  7. printf("Enter a string:\n");
  8. scanf(“%s”,str); /* 也可以gets(str);puts(str); */
  9. for(i=0,j=strlen(str)-1;i<j;i++,j--)
  10. {
  11. c=str[i];
  12. str[i]=str[j];
  13. str[j]=c;
  14. }
  15. printf("\nReversed string:\n%s\n",str);
  16. }

本文分享自华为云社区《C语言非数值计算常用经典算法之排序》,原文作者:Jack20。

点击关注,第一时间了解华为云新鲜技术~

五种C语言非数值计算的常用经典排序算法的更多相关文章

  1. Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现

    2017年4月29日~5月1日,国际劳动节, 三天的小长假. 在国内,小长假往往是这样的: 然而我当时在戏称为"德村"(德国农村)的Walldorf出差并且住在Wiesloch, ...

  2. 【最全】经典排序算法(C语言)

    算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首 ...

  3. 数据结构中常用的排序算法 && 时间复杂度 && 空间复杂度

    第一部分:数据结构中常用的排序算法 数据结构中的排序算法一般包括冒泡排序.选择排序.插入排序.归并排序和 快速排序, 当然还有很多其他的排序方式,这里主要介绍这五种排序方式. 排序是数据结构中的主要内 ...

  4. java SE 常用的排序算法

    java程序员会用到的经典排序算法实现 常用的排序算法(以下代码包含的)有以下五类: A.插入排序(直接插入排序.希尔排序) B.交换排序(冒泡排序.快速排序) C.选择排序(直接选择排序.堆排序) ...

  5. JavaScript实现常用的排序算法

    ▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...

  6. 七种经典排序算法及Java实现

    排序算法稳定性表示两个值相同的元素在排序前后是否有位置变化.如果前后位置变化,则排序算法是不稳定的,否则是稳定的.稳定性的定义符合常理,两个值相同的元素无需再次交换位置,交换位置是做了一次无用功. 下 ...

  7. 七种常见经典排序算法总结(C++实现)

    排序算法是非常常见也非常基础的算法,以至于大部分情况下它们都被集成到了语言的辅助库中.排序算法虽然已经可以很方便的使用,但是理解排序算法可以帮助我们找到解题的方向. 1. 冒泡排序 (Bubble S ...

  8. 常用Java排序算法

    常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...

  9. C#中常用的排序算法的时间复杂度和空间复杂度

    常用的排序算法的时间复杂度和空间复杂度   常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 ...

随机推荐

  1. [leetcode712]204. Count Primes寻找范围内的素数

    厄拉多塞筛选法,就是哈希表记录素数的倍数 public int countPrimes(int n) { /* 牛逼哄哄的厄拉多塞筛选法 就是从2开始,每找到一个素数,就把n以内的这个数的倍数排除 记 ...

  2. String Boot有哪些优点

    a.减少开发,测试时间和努力. b.使用 JavaConfig 有助于避免使用 XML.c.避免大量的 Maven 导入和各种版本冲突. d.通过提供默认值快速开始开发.没有单独的 Web 服务器需要 ...

  3. 改进你的c#代码的5个技巧(二)

    在本文中,我将向你展示c#编程的5个最佳实践.我从日常编程经验中学到了这些实践.我在release模式下测试了所有的代码,并在开发环境稳定后进行了截屏.我想你会喜欢这些建议的. 在使用数据类型之前选择 ...

  4. 分享一个的c++写的,模仿awk的框架类CAwkDoc

    这是我好多年前,模仿awk写的. awk大家都比较熟悉,使用awk处理文件,读取文件,分割字段这些工作awk自己帮你实现了. 程序员只要编写业务逻辑代码,并且awk还提供了很多常用的字符串操作函数,可 ...

  5. 项目中处理数据常用Excel公式

    ="'"&A1&"'," 需求:是大佬给了excel,里面是700多个单号,要我从生产的数据库中查询出每个单号对应的类型,这时需要查数据库,我决 ...

  6. CentOS 6安装Gitlab

    1. 保证CentOS 6能连接网络 . 2.安装依赖: sudo yum install -y curl policycoreutils-python openssh-server cronie s ...

  7. 【Linux】kali 安装 python3 和 pip3(亲测有效)

    [Linux]kali 安装 python3 和 pip3 引言:   在使用kali的时候,经常会用到各种工具以及脚本,而大多数脚本都是以python编写的,但是烦就烦在python有2个版本,有些 ...

  8. SpringMVC文件的上传与下载实现

    单文件上传 首先创建项目,开发工具是IDEA,选择Spring项目,勾选上Spring和SpringMVC. 然后命名,最后完成. 默认生成配置文件在web/WEB-INF下. 首先导入需要的jar包 ...

  9. selenium爬虫 | 爬取疫情实时动态(二)

    '''@author:Billie更新说明:1-28 17:00 项目开始着手,spider方法抓取到第一条疫情数据,save_data_csv方法将疫情数据保存至csv文件1-29 13:12 目标 ...

  10. [APUE] 文件 I/O

    文件操作相关 API:open, read, write, lseek, close. 多进程共享文件的相关 API:dup, dup2, fcntl, sync, fsync, ioctl. 文件操 ...