【专题七】排序算法

一、选择排序

(1) 基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在待排序的数列的最前,直到全部待排序的数据元素排完。
(2)排序过程:
【示例】:
初 始 关键字 [49 38 65 97 76 13 27 49]
第一趟排序后 13[38 65 97 76 49 27 49]
第二趟排序后 13 27[65 97 76 49 38 49]
第三趟排序后 13 27 38 [97 76 49 65 49]
第四趟排序后 13 27 38 49 [76 97 65 49]
第五趟排序后 13 27 38 49 49 [97 65 76]
第六趟排序后 13 27 38 49 49 65 [97 76]
第七趟排序后 13 27 38 49 49 65 76 [97]
最后排序结果 13 27 38 49 49 65 76 97
举个栗子:
输入n个数,将n个数按从小到大的顺序输出(n<=10000)。
输入样例:
8
49 38 65 97 76 13 27 49
输出样例:
13 27 38 49 49 65 76 97
即:
①读入数据存放在a数组中。
②在a[1]~a[n]中选择值最小的元素,与第1位置元素交换,则把最小值元素放入a[1]中。
③在a[2]~a[n]中选择值最小的元素,与第2位置元素交换,则把最小值元素放入a[2]中,……
④直到第n-1个元素与第n个元素比较排序为止。
程序实现方法:用两层循环完成算法,外层循环i控制当前序列最小值存放的数组位置,内层循环j控制从i+1到n序列中选择最小的元素所在位置k。

二、冒泡排序

冒泡排序的思想:以n个人站队为例,从第1个开始,依次比较相邻的两个是否逆序对(高在前,矮在后),若逆序就交换这两人,即第1个和第2个比,若逆序就交换两人,接着第2个和第3个比,若逆序就交换两人,接着第3个和第4个比,若逆序就交换两人,……,直到n-1和n比较,经过一轮比较后,则把最高的人排到最后,即将最高的人像冒泡一样逐步冒到相应的位置。原n个人的排序问题,转换为n-1个人的排序问题。第二轮从第1个开始,依次比较相邻的两个人是否逆序对,若逆序就交换两人,直到n-2和n-1比较。如此,进行n-1轮后,队列为有序的队列。
从上述分析中可以看出,每进行一轮的比较之后,n个数的排序规模就转化为n-1个数的排序规模。
例如有6个元素需要排序:
6 5 3 4 1 2
第一趟排序:

在这里插入图片描述
二
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
即:
①读入数据存放在a数组中。
②比较相邻的前后两个数据,如果前面数据大于后面的数据,就将两个数据交换。
③对数组的第0个数据到n-1个数据进行一次遍历后,最大的一个数据就“冒”到数组第n-1个位置。
④n=n-1,如果n不为0就重复前面二步,否则排序完成。
程序实现方法:用两层循环完成算法,外层循环i控制每轮要进行多少次的比较,第1轮比较n-1次,第2轮比较n-2次,……,最后一轮比较1次。内层循环j控制每轮i次比较相邻两个元素是否逆序,若逆序就交换这两个元素。

三、插入排序

插入排序思想:就像打牌时抓牌的情景,为了方便打牌,抓牌时一般一边抓牌一边按花色和大小插入恰当的位置,当抓完所有的牌时,手中的牌便是有序的,这排序方法即插入排序。
当读入一个元素时,在已经排序好的序列中,搜寻它正确的位置,再放入读入的元素。但不该忽略一个重要的问题:在插入这个元素前,应当先将将它后面的所有元素后移一位,以保证插入位置的原元素不被覆盖。
例如:设n=8,数组a中8个元素是: 36,25,48,12,65,43,20,58,执行插入排序程序后,其数据变动情况:

第0步:[36] 25 48 12 65 43 20 58
第1步:[25 36] 48 12 65 43 20 58
第2步:[25 36 48] 12 65 43 20 58
第3步:[12 25 36 48] 65 43 20 58
第4步:[12 25 36 48 65] 43 20 58
第5步:[12 25 36 43 48 65] 20 58
第6步:[12 20 25 36 43 48 65] 58
第7步:[12 20 25 36 43 48 58 65]

#include<iostream>
using namespace std;
const int MAXN=10001;
int main()
{
      int n,i,j,k;  
      float temp,a[MAXN];
      cin>>n;
      for (i=0;i<n;i++)
         cin>>a[i];                      //输入n个数 
    for(i=0; i<n; i++)
    { 
       for(j=i-1; j>=0; j--)          //在前面有序区间中为a[i]找合适的插入位置 
         if (a[j]<a[i]) break;        //找到比a[i]小的位置就退出,插入其后 
       if (j!=i-1)
       {
          temp=a[i];                   //将比a[i]大的数据向后移 
          for(k=i-1;k>j;k--)
             a[k+1]=a[k];              //将a[i]放在正确位置上 
          a[k+1]=temp;
       }
    }
    for (i=0;i<n;i++)
        cout<<a[i]<<" ";            //输出排序的结果 
   return 0; 
}

四、桶排序

桶排序的思想是若待排序的值在一个明显有限范围内(整型)时,可设计有限个有序桶,待排序的值装入对应的桶(当然也可以装入若干个值),桶号就是待排序的值,顺序输出各桶的值,将得到有序的序列。
栗子:输入n个0到100之间的整数,由小到大排序输出。

#include<iostream>
#include <cstring>
using namespace std;
int main()
     int b[101],n,i,j,k;
     memset(b,0,sizeof(b));             //初始化
     cin>>n;
     for (i=1;i<=n;i++)
     {
         cin>>k; b[k]++;                     //将等于k的值全部装入第k桶中
     }
     for (i=0;i<=100;i++)                  //输出排序结果
       while (b[i]>0)                          //相同的整数,要重复输出
       {
           cout<<i<<" "; b[i]--;             //输出一个整数后,个数减1
        }
      cout<<endl;    
}


五、稳定性比较

稳定性比较
插入排序、冒泡排序及其他线形排序是稳定的。
选择排序、快速排序、堆排序是不稳定的。

时间复杂度比较

插入排序、冒泡排序、选择排序的时间复杂性为O(n2);快速排序、堆排序、归并排序的时间复杂性为O(nlog2n);桶排序的时间复杂性为O(n);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值