算法:C++ 实现选择排序、冒泡排序、选择排序、桶排序

x33g5p2x  于2022-04-10 转载在 其他  
字(4.1k)|赞(0)|评价(0)|浏览(534)

1、选择排序

基本思想:从头至尾扫描序列,每一趟从待排序元素中找出最小(最大)的一个元素,与第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序序列。

原始序列:45 32 65 98 5 42 11 61
1)从序列中取出最小的元素5,将5同序列第一个元素交换,此时产生仅含一个元素的有序序列,序列减一;

结果:5 [11 32 42 45 65 98]

2)从序列中取出最小的元素11,将11同序列第一个元素交换,此时产生仅两个元素的有序序列,序列减一;

结果:5 11 [32 42 45 65 98] …
结果:5 11 32 [42 45 65 98]
结果:5 11 32 42 [45 65 98]
结果:5 11 32 42 45 [65 98]
结果:5 11 32 42 45 65 [98]
最后一个元素肯定是最大元素,排序直接生产一个有序的序列;
结果:13、27、38、49、49、65、76、97

  1. #include <iostream>
  2. #include <cstdio>
  3. using namespace std;
  4. const int Max = 100; //定义数组长度
  5. int main(){
  6. int n,k;
  7. int a[Max]; //定义
  8. cout<<"请输入n个数:";
  9. cin>>n;
  10. cout<<"输入数据,以空格隔开:"<<endl;
  11. for(int i=0;i<n;++i)
  12. cin>>a[i];
  13. for(int i=0;i<n;++i){
  14. k=i; //先默认a[i]为最小值
  15. for(int j=i+1;j<n;++j){
  16. if(a[k]>a[j]) k=j; //判断最小值的位置,赋给k,那k就是最小值的位置
  17. }
  18. int temp;
  19. if(k!=i){ //k的位置不是i,那么就交换数值;交换后,最小值就是在a[i]的位置
  20. temp=a[i];
  21. a[i]=a[k];
  22. a[k]=temp;
  23. }
  24. }
  25. cout<<"选择排序后输出:"<<endl;
  26. for(int i=0;i<n;++i)
  27. cout<<a[i]<<" ";
  28. }

  1. 稳定性:在选择排序中,每趟都会选出最大元素与最小元素,然后与两端元素交换,此时,待排序序列中如果存在与原来两端元素相等的元素,稳定性就可能被破坏。如[5,7,5,21,10],在array[0]与array[3]元素交换时,序列的稳定性就被破坏了,所以选择排序是一种不稳定的排序算法。
  2. 时间复杂度:选择排序的时间复杂度为O(n2)。
  3. 适用场景:待排序序列中,元素个数较少时。

2、冒泡排序

基本思想:相邻的元素两两比较,较大的数下沉(排后面),较小的数冒起来(排前面),这样一趟比较下来,最大(小)值就会排列在末端。整个过程如同气泡冒起,因此被称作冒泡排序。
冒泡排序的步骤:

  1. 读入数据放在数组a中。
  2. 比较相邻的两个元素,如果第一个比第二个大,就将两个数据交换。
  3. 从数组的第0个数据到n-1个数据进行一次遍历,重复2的操作,这样最大的数就“冒”到数组最后一个位置了。
  4. 最后一个已经排好,所以n=n-1,赋值后的n不为0,就重复上面2,3。
  1. #include <iostream>
  2. #include <cstdio>
  3. using namespace std;
  4. const int Max = 100; //定义数组长度
  5. int main(){
  6. int n,k;
  7. int a[Max]; //定义
  8. cout<<"请输入n个数:";
  9. cin>>n;
  10. cout<<"输入数据,以空格隔开:"<<endl;
  11. for(int i=0;i<n;++i) //第1步
  12. cin>>a[i];
  13. for(int i=n-1;i>0;--i){ //第4步
  14. for(int j=0;j<i;++j){ //第3步
  15. int temp;
  16. if(a[j]>a[j+1]) { //第2步
  17. temp=a[j+1];
  18. a[j+1]=a[j];
  19. a[j]=temp;
  20. }
  21. }
  22. }
  23. cout<<"冒泡排序后输出:"<<endl;
  24. for(int i=0;i<n;++i)
  25. cout<<a[i]<<" ";
  26. cout<<endl<<"从大到小:"<<endl;
  27. for(int i=n-1;i>=0;--i)
  28. cout<<a[i]<<" ";
  29. }

  1. 稳定性:在冒泡排序中,遇到相等的值,是不进行交换的,只有遇到不相等的值才进行交换,所以是稳定的排序方式。
  2. 时间复杂度:如果待排序序列的初始状态恰好是我们希望的排序结果(如升序或降序),一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数M均达到最小值;冒泡排序最好的时间复杂度为O(n),冒泡排序的最坏时间复杂度为O(n^2)。综上,冒泡排序总的平均时间复杂度为O(n ^2)。

  1. 适用场景:冒泡排序适用于数据量很小的排序场景,因为冒泡的实现方式较为简单。

3、选择排序

基本思想:将初始数据分为有序部分和无序部分,每一步将一个无序部分的数据插入到前面已经排好序的有序部分中,直到插完所有元素为止。
步骤如下:每次从无序部分中取出一个元素,与有序部分中的元素从后向前依次进行比较,并找到合适的位置,将该元素插到有序组当中。

假如有[5,2,3,9,4,7]六个元素,下面就以排序过程中的一个步骤(此时有序部分为[2,3,5,9],无序部分为[4,7],接下来要把无序部分的“4”元素插入到有序部分),来展示一下插入排序的运行过程。

  1. 首先,原始的数组元素是这样的。

其中,浅绿色代表有序部分,黄色代表无序部分。

  1. 在无序部分中挑出要插入到有序部分中的元素。

  1. 将要插入的元素与左边最近的有序部分的元素进行比较。由于4 < 9,所以9向后移,4向前移。
          

  2. 继续将要插入的元素与左边最近的有序部分的元素进行比较。由于4 < 5,所以5向后移,4继续向前移。

  3. 继续将4与3比较。由于4 > 3,所以不再向前比较,插入到当前位置。

  4. 此时有序部分,由[2,3,5,9]变成[2,3,4,5,9]。

  1. #include <iostream>
  2. #include <cstdio>
  3. using namespace std;
  4. const int Max = 100; //定义数组长度
  5. int main(){
  6. int n,k,i,j,temp;
  7. int a[Max]; //定义
  8. cout<<"请输入n个数:";
  9. cin>>n;
  10. cout<<"输入数据,以空格隔开:"<<endl;
  11. for(int i=0;i<n;++i)
  12. cin>>a[i];
  13. for(i=1;i<n;++i)
  14. {
  15. temp=a[i];
  16. for(j=i-1;j>=0 &&a[j]>temp ;--j){ //满足条件执行,不满足就跳过
  17. a[j+1]=a[j]; //当a[j]>temp,把元素后移一位,直到--j=-1
  18. }
  19. a[j+1]=temp; //--j=-1后再+1,把temp的值赋给a[--j+1]
  20. }
  21. cout<<"插入排序后输出:"<<endl;
  22. for(int i=0;i<n;++i)
  23. cout<<a[i]<<" ";
  24. return 0;
  25. }

  1. 稳定性:在使用插入排序时,元素从无序部分移动到有序部分时,必须是不相等(大于或小于)时才会移动,相等时不处理,所以直接插入排序是稳定的。
  2. 时间复杂度:在插入排序中,当待排序序列是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较n- 1次,时间复杂度为O(n)。最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(n2)。平均来说,array[1…j-1]中的一半元素小于array[j],一半元素大于array[j]。插入排序在平均情况运行时间与最坏情况运行时间一样,是O(n2)。
  3. 适用场景:待排序序列的元素个数不多(<=50),且元素基本有序。

4、桶排序

将待排序的数值k,装入第k个桶,桶号就是待排序的数值,顺序输出各桶的值,得到有序的序列。
步骤:

  1. 先创建数组并初始化值为0。
  2. 把k值装入第k个桶(cin>>k,a[k]),把值+1,同一个桶每装一个就+1。(a[k]++)。
  3. 当a[i]>0,代表第i个桶是有值的,输出i的序号(也就是i值),桶就少了一个值(a[i]–)。

例如:输入n个0-99的整数值,从小到大排序输出。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int Max = 100; //定义数组长度
  6. int main(){
  7. int n,k,i,j,temp;
  8. int a[Max]; //定义
  9. memset(a,0,sizeof(a)); //初始化数组值0
  10. cout<<"请输入n个数:";
  11. cin>>n;
  12. for(i=1;i<=n;++i){
  13. cin>>k; //输入数值
  14. a[k]++; //桶号个数+1
  15. }
  16. for(i=0;i<100;i++){ //从小到大输出
  17. while(a[i]>0) //判断有桶号
  18. {
  19. cout<<i<<" "; //输出桶号=桶存的数值
  20. a[i]--; //桶号个数-1,直到没有个数
  21. }
  22. }
  23. cout<<endl;
  24. return 0;
  25. }

**参考文章:**插入排序部分

相关文章