c++/c语言 系统全面学习一维数组排序的3种基本方法

前言:

我们先了解一下数组

数组就是一组相同类型的变量,它们往往都是为了表示同一批对象的统一属性,如一个班级所有同学的身高、全球所有国家的人口数等。 数组可以是一维的,也可以是二维或多维的。

再来看看一维数组的定义:

定义一维数组的格式如下: 类型标识符 数组名 [ 常量表达式 ]; 其中,类型标识符可以是任何基本数据类型,也可以是结构体等构造类型,相同类型的数组可以一起定义。数组名必须是合法的标识符。常量表达式的值即为数组元素的个数。


现在步入正题:

什么是排序?

“排序”就是按照某个关键字的大小,将若干对象从小到大或者从大到小进行重新排列。关键字是对象的某一个属性,它可以是任何基本数据类型,甚至结构体等。 例如,体育课上我们会按照身高从矮到高站队,这就是“升序”排序,身高是我们每个人的一个属性,也就是排序的关键字。再如,将所有单词按照“字典序”倒过来排序,如zoo,yes,most,key,computer,book,bad,apple等,就是“降序”排序,关键字的类型就是字符串。 排序算法非常多,其中最基本的有选择排序、冒泡排序和插入排序三种。其本质上都是通过数组中的元素比较和交换来实现的,关键是数组下标的分析。


首先看一道题目:

例1:站队

【问题描述】 给出 n 个同学的身高,请根据他们的身高升序排列并输出排序结果。

【输入格式】

第一行 1 个正整数 n,表示有 n 个同学的身高,2<n≤100。

第二行包含 n 个正整数,之间用一个空格隔开,表示 n 个同学的身高。每个同学的身高都在 150~200 厘米之间。

【输出格式】 一行 n 个正整数,之间用一个空格隔开,表示 n 个同学根据身高升序排列的结果。 【输入样例】 7 180 170 176 160 155 150 160

【输出样例】 150 155 160 160 170 176 180

废话少说,直接进入我们第一种方法:

算法1:选择排序

选择排序的基本思想是:每一趟从待排序的数据中,通过“打擂台”比较选出最小元素,放在这些数据的最前面。

比如:第一趟把 n 个数中(第 1 个到第 n 个)最小的放在第一个位置,第二趟把剩余的 n-1 个数中(第 2 个到第 n 个)最小的放在第二个位置,第三趟把剩余的 n-2 个数中(第 3 个到第 n 个)最小的放在第三个位,……第 n-1 趟把剩下的 2 个数中(第 n-1 个到第 n 个)最小的放在第 n-1 个位置,剩下的最后一个数(第 n 个)一定最大,自然落在了第 n个位置。

附一个图片加以理解:

附上AC选择排序代码: 

//p5-5-1a,选择排序
#include<iostream>
using namespace std;
int main(){
    int n,i,j,k,temp,h[101];
    cin >> n;
    for(i = 1; i <= n; i++) cin >> h[i];
    for(i = 1; i <= n; i++){
         k = i;
         for(j = i+1; j <= n; j++)
             if(h[j] < h[k]) k = j;// 在 i~n 之间的最小元素
         temp = h[i];
         h[i] = h[k];
         h[k] = temp;// 将 i~n 之间的最小元素放到第 i 个位置
    }
    for(i = 1; i < n; i++) cout << h[i] <<  “ “ ;
    cout << h[n] << endl;
    return 0;
}

算法2:冒泡排序 

冒泡排序的基本思想是:

从第一个数开始,依次不断比较相邻的两个元素,如果“逆序”就交换。这样,一趟排序结束后,最大的元素就放在了第 n 个位置了。

附一个图片加以理解:

 

附上AC冒泡排序代码:

//p5-5-1b,冒泡排序
#include<iostream>
using namespace std;
int main(){
    int n,i,j,temp,h[101];
    cin >> n;
    for(i = 1; i <= n; i++) cin >> h[i];
    for(i = 1; i < n; i++)
         for(j = 1; j <= n-i; j++)
                if(h[j] > h[j+1]){
                           temp = h[j];
                           h[j] = h[j+1];
                           h[j+1] = temp;
                }
    for(i = 1; i < n; i++) cout << h[i] <<  “ “ ;
    cout << h[n] << endl;
    return 0;
}

tips: 对于冒泡排序,我们还可以做些算法“优化”。如果一趟排序下来,都没有任何“逆序”数对,即没有发生“交换”操作,则说明已经排好序了。此时,就可以立刻退出循环。

算法3:桶排序

先附上题目:

例2:商品排序

【问题描述】

某商场的仓库中有 n 件商品,每件商品的价格在 0~1000 之间(价格为 0 的商品为赠品)。 现在商场经理要求将这 n 件商品按价格由低到高排序。请编程输出 n 件商品排序后的情况。

【输入格式】 第一行一个正整数 n,表示有 n 件商品,1≤n≤100000。 接下来的 n 行,每行一个整数,表示第 i 件商品的价格。

【输出格式】 n 行,每行输出一个整数。

问题分析】

本题可以选用学过的任意一种排序算法实现,但是测试程序发现会“超时”,因为本题最多有 100000 件商品,三种排序都需要两层循环嵌套。 其实,分析数据发现一个重要特征:数据虽然很多,但是数据范围比较小。这种情况下,可以使用另外一种排序算法——桶排序。定义一个 int 型数组 num[1001],num[x]记录整数 x 出现的次数,初始化都为 0,每读到一个数 x,就执行 num[x] = num[x]+1。输出时,从 0 ~ 1000 穷举 x,每个 x  输出 num[x]次。

//p5-6-2,桶排序
#include<iostream>
using namespace std;
int n,i,j,number,num[1001];
int main(){
    cin >> n;
    for(i = 1; i <= n; i++){
         cin >> number;
         num[number]++;// 记录整数 number 出现的次数
    }
    for(i = 0; i < 1001; i++)
         for(j = 1; j <= num[i]; j++)
               cout << i <<endl;// 输出 num[i] 次 i
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值