C++ 详解 —— 一维数组排序

“排序”就是按照某个关键字的大小,将若干对象从小到大或者从大到小进行重新排列。关键字是对象的某一个属性,它可以是任何基本数据类型,甚至结构体等。

例如,体育课上我们会按照身高从矮到高站队,这就是“升序”排序,身高是我们每个人的一个属性,也就是排序的关键字。

排序算法非常多,其中最基本的有选择排序、冒泡排序和插入排序三种。其本质上都是通过数组中的元素比较和交换来实现的,关键是数组下标的分析。

例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

一、选择排序

选择排序的基本思想是:每一趟从待排序的数据中,通过“打擂台”比较选出最小元素,放在这些数据的最前面。这样,第一趟把n个数中(第1个到第n个)最小的放在第一个位置,第二趟把剩余的n-1个数中(第2个到第n个)最小的放在第二个位置,第三趟把剩余的n-2个数中(第3个到第n个)最小的放在第三个位,……第n-1趟把剩下的2个数中(第n-1个到第n个)最小的放在第n-1个位置,剩下的最后一个数(第n个)一定最大,自然落在了第n个位置。

//例1 选择排序参考代码
#include<bits/stdc++.h>
using namespace std;
int a[50],n;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];

	for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++)
                  if(a[i]>a[j])
                    swap(a[i],a[j]);
	}

	for(int i=1;i<=n;i++)
		cout<<a[i]<<" ";
	
	return 0; 
} 

处理逻辑:

~~~1.png

二、冒泡排序

冒泡排序的基本思想是:从第一个数开始,依次不断比较相邻的两个元素,如果“逆序”就交换。这样,一趟排序结束后,最大的元素就放在了第n个位置了。对于样例数据,第一趟冒泡排序的过程如下:

~~~2.png

用同样的方法,第二趟把剩余的前n-1个数中最大的交换到第n-1个位置,第三趟把剩余的前n-2个数中最大的交换到第n-2个位置,……经过n-1趟,排序结束。

//例1 冒泡排序参考代码
#include<bits/stdc++.h>
using namespace std;
int a[50],n;
int main(){
  cin>>n;
  for(int i=1;i<=n;i++)
      cin>>a[i];
  		
  for(int i=1;i<n;i++){
      for(int j=1;j<=n-i;j++){
          if(a[j]>a[j+1])
              swap(a[j],a[j+1]);
      }
  }
  	
  for(int i=1;i<=n;i++)
      cout<<a[i]<<" ";

  return 0; 
} 

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

三、插入排序

插入排序的基本思想是:把所有待排序元素分成前后两段,前一段是已经排好序的,后一段是待排序的。每一趟都是把后一段的第一个数“插入”到前一段的某一个位置,保证前一段仍然是有序的。开始时,第1个数作为前一段肯定是有序的;第一趟,把第2个数插入进去,保证前2个数有序;第二趟,把第3个数插入进去,保证前3个数有;……第n-1趟,把第n个数插入进去,保证n个数都有序。

~~~3.png

//例1 插入排序参考代码
#include<bits/stdc++.h>
using namespace std;
int a[50],n,t,k;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    		
    for(int i=2;i<=n;i++){
        t=a[i];
        k=1;
        while(a[k]<=t && k<i)
            k++;
        for(int j=i-1;j>=k;j--)
            a[j+1]=a[j];
        a[k]=t;
    }
    	
    for(int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    	
    return 0; 
} 

四、计数排序

计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。

//例1 计数排序参考代码
#include<bits/stdc++.h>
using namespace std;
int a[50],x[50],n,maxx=-1e9,minn=1e9;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x[i];	
        a[x[i]]++;
        if(x[i]>maxx) maxx=x[i];
        if(x[i]<minn) minn=x[i];
    }		
        for(int i=minn;i<=maxx;i++){
            for(int j=1;j<=a[i];j++)
                  cout<<i<<" ";
    }
    	
    return 0; 
} 

下面是各自动画演示:

1、选择排序

2.gif

2、冒泡排序

1.gif

3、插入排序

3.gif

四、计数排序 

4.gif

 

 

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值