学习笔记——数组排序:选择,冒泡

一、排序
1、排序的目的:把数组中的各个元素按照从小到大或者从大到小的顺序排列(也有可能是
别的顺序),排序后的结果保存在同一个数组中。
例如:2 7 9 5 1 从小到大排序后的结果是 1 2 5 7 9
2、排序的方法:选择排序法、冒泡排序法、…
二、选择排序法
1.
第一轮从 a[0]~a[n-1]中找到最小值,与 a[0]交换值,把最小值放在 a[0]的位置
第二轮从 a[1]~a[n-1]中找出最小值,与 a[1]交换值,把最小值放在 a[1]的位置
最后一轮从 a[n-2]~a[n-1]中找出最小值,与 a[n-2]交换值,把最小值放在 a[n-2]的位置
n-1 轮后,前 n-1 个元素放好了,最后的 a[n-1]自然是最大的元素
核心问题:在一堆数组元素中找出最小值对应的下标。
例: 使用选择排序法,对随机 7 个整数进行从小到大的排序
初始: [ 49 38 65 97 76 13 27]
一次: 13 [ 38 65 97 76 49 27 ]
二次: 13 27 [ 65 97 76 49 38 ]
三次: 13 27 38 [ 97 76 49 65]
四次: 13 27 38 49 [ 76 97 65 ]
五次: 13 27 38 49 65 [ 97 76 ]
六次: 13 27 38 49 65 76 [97]
2.选择排序法核心代码(元素类型: int 、用函数select实现)
     //使用选择排序法,把长度为 n 的整型数组 a 进行从小到大的排序
void selectSort(int a[ ], int n) //注意把数组变量定义成函数形参时的写法
{
for(int i = 0; i < n-1; i++)
{
     //在 a[i]到 a[n-1]中,找到最小的元素对应的下标 min,交换 a[min]和 a[i]
int min=i; //假设第 i 个元素最小,min 负责记录当前看到的最小元素下标
for(int j = i+1; j < n; j++) //看看余下的其他元素有没有更小的,j 代表下标
{
if(a[j]<a[min]) 
{
min=j; //如果看到更小的,就修改 min 值 } }
swap(a[i],a[min]); //这时 a[min]是最小的,与 a[i]交换就换到了应该的位置
} 
}
3、选择排序法核心代码(元素类型:int、另一种写法)
思想:一旦发现大小关系不对(即下标在前面的 a[i]比下标在后面的 a[j]大),则交换
void selectSort(int a[ ], int n) 
//如果元素类型 double,则 void selectSort(double a[ ], int n)
{
for (int i = 0; i < n; i++)
 {
for (int j = i + 1; j < n; j++)
  {
if (a[i] > a[j])
   {
swap(a[i], a[j]);
   } 
  } 
 } 
}
4、用函数模板实现选择排序(元素类型:任意)
template<typename T>
void selectSort(T a[ ], int n)
{
for (int i = 0; i < n; i++)
 {
for (int j = i + 1; j < n; j++)
  {
if (a[i] > a[j])
   {
swap(a[i], a[j]);
   }
  } 
 } 
}
5、选择排序法完整代码
例:输入一个正整数 m,然后输入 m 个整数,对这 m 个整数使用选择排序法从小到大排序,
然后输出排序后的 m 个整数,每个整数输出后都要换行。
#include<iostream>
using namespace std;
template<typename T>
void selectSort(T a[ ], int n)
{
for (int i = 0; i < n; i++)
 {
for (int j = i + 1; j < n; j++)
  {
if (a[i] > a[j])
   {
swap(a[i], a[j]);
   } 
  } 
 } 
}
int main()
{
int m;
cin >> m;
int *a = new int[m];
for (int i = 0; i < m; i++)
 {
cin >> a[i];
 }
selectSort(a, m); //注意调用函数时,把数组变量当函数实参的写法
for (int i = 0; i < m; i++)
 {
cout << a[i] << endl;
 }
delete[ ]a;
return 0;
}
三、冒泡排序法
1、使用冒泡排序法,把长度为 n 的整型数组 a 从小到大排序:
每次都是两个下标相邻的数字进行比较,如果大小关系不对(即前一个数比后一个数大),
则交换它们,以保证前一个数小于后一个数。
每轮循环都可以产生一个当前最大的数,这个数在以后的循环中不参与比较。
例:用冒泡法对 5 个整数进行从小到大的排序
初始:
[9 8 5 7 6]
第一轮:
[ 8 9 5 7 6]
[8 5 9 7 6]
[8 5 7 9 6]
[8 5 7 6 ( 9 )]
第一轮结束后,最后一个数字(9)可以确定是最大的数字。
第二轮:
[ 5 8 7 6 (9)]
[5 7 8 6 (9)]
[5 7 6 ( 8 ) (9)]
第二轮结束后,倒数第二个数字(8)可以确定是第二大的数字。
第三轮:
[ 5 7 6 (8) (9)]
[5 6 ( 7 ) (8) (9)]
第三轮结束后,倒数第三个数字(7)可以确定是第三大的数字。
第四轮:
[ 5 ( 6 ) (7) (8) (9)]
第四轮结束后,倒数第四个数字(6)可以确定是第四大的数字。
最后一个数字(5)一定是第五大的数字(即最小的数字)
2、选择冒泡排序法核心代码(元素类型: int 、用函数实现)
//使用冒泡排序法,把长度为 n 的整型数组 a 进行从小到大的排序
void bubbleSort(int a[ ], int n)
{
 for (int i = n - 2; i >= 0; i--)
 {
  for (int j = 0; j <= i; j++)
  {
   if (a[j] > a[j + 1])
   {
    swap(a[j], a[j + 1]);
   } 
  }
 } 
}
代码解读:
(1)当 i = n - 2 时,j 的循环从 0 到 n-2,j 的循环里进行的比较有:
a[0]和 a[1],a[1]和 a[2],a[2]和 a[3],…,a[n-2]和 a[n-1]
那么 a[0]到 a[n-1]中最大的数字最终保存在了 a[n-1]中。
(2)当 i = n - 3 时,j 的循环从 0 到 n-3,j 的循环里进行的比较有:
a[0]和 a[1],a[1]和 a[2],a[2]和 a[3],…,a[n-3]和 a[n-2]
那么 a[0]到 a[n-2]中最大的数字最终保存在了 a[n-2]中。
(3)当 i 最后一次循环等于 0 时,j 的循环只循环一次(j=0),j 的循环里进行的比较有:
a[0]和 a[1],那么 a[0]和 a[1]中最大的数字最终保存在了 a[1]中。
3、用函数模板实现冒泡排序(元素类型:任意)
template<typename T>
void bubbleSort(T a[], int n)
 {
for (int i = n - 2; i >= 0; i--)
  { 
    for (int j = 0; j <= i; j++)
     {
      if (a[j] > a[j + 1])
       {
        swap(a[j], a[j + 1]);
       }
     }
  }
 }
4、冒泡排序法完整代码
例:输入一个正整数 m,然后输入 m 个整数,对这 m 个整数使用冒泡排序法从小到大排序,
然后输出排序后的 m 个整数,每个整数输出后都要换行。
#include<iostream>
using namespace std;
template<typename T>
void bubbleSort(T a[], int n)
{
for (int i = n - 2; i >= 0; i--) {
for (int j = 0; j <= i; j++)
{
if (a[j] > a[j + 1])
{
swap(a[j], a[j + 1]);
} } } }
int main()
{
int m;
cin >> m;
int* a = new int[m];
for (int i = 0; i < m; i++)
{
cin >> a[i];
}
bubbleSort(a, m);
for (int i = 0; i < m; i++)
{
cout << a[i] << endl;
}
delete[ ]a;
return 0;
}
说明:如果是固定长度的数组,例如 10 个浮点数从小到大排序,那么只需要修改主函数
const int m = 10;
double a[m];
//...
并且删除 delete[ ]a;
此时 bubbleSort 函数或者 selectSort 函数,如果使用函数模板定义,不需要修改函数代码。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值