这几天,我(蒟蒻)搞了一下排序算法,感觉收获挺多的,今天就总结一下吧。
常见的排序算法有冒泡排序、插入排序、桶排序(简化版)、快速排序、归并排序以及利用C++STL库函数中的sort函数进行排序。
这篇文章就主要介绍前三个,后面的三种实现在下一篇中介绍。
1、冒泡排序
冒泡排序可以说是最基本的排序算法了。它的时间复杂度为O(n^2)。冒泡排序的优点是简单,代码易于实现,缺点是时间复杂度较大,用于大规模数据则容易超时。
***基本思想**:
每次比较两个相邻的元素,如果它们的顺序错误就把它们交换过来。*(节选自《啊哈!算法》)
所以,对于要排序的N个数,需循环比较N-1次,每次循环找出剩下元素中最大(小)的值。
代码实现:
void BubbleSort()
{
int i1, i2;
for(int i1=0;i1<N-1;i1++)//N个数排序,只进行N-1次循环
for(int i2=0;i2<N-1-i1;i2++)//从剩下的数中挑选最大的
if (num[i2] > num[i2 + 1])//交换
{
int temp = num[i2];
num[i2] = num[i2 + 1];
num[i2 + 1] = temp;
}
}
2、插入排序
插入排序和冒泡排序一样也是初学排序算法时必须掌握的,它的时间复杂度为O(n^2),缺点也是时间复杂度较大,不适合大规模数据。
基本思想:
将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1趟排序!!*!
文字原文链接:https://blog.youkuaiyun.com/weixin_43956598/article/details/90181567;
图片原文链接:https://blog.youkuaiyun.com/qq_41055045/article/details/103463918?utm_source=app
代码实现:
void InsertionSort()//从小到大排列num[0]到num[N-1]
{
for (int i = 1; i < N; i++)//从倒数第二个元素进行插入排序
{
if (num[i] < num[i - 1])//如果当前元素小于前一个元素
{
int temp = num[i];
int i1;
for (i1=i-1; i1 >= 0; i1--)
if (num[i1] > temp)//比较和前一个元素的大小
num[i1 + 1] = num[i1];//使较大元素后移,留出一个空位
else
break;
num[i1+1] = temp;//插入空位
}
}
}
3、简化版桶排序
桶排序的算法比较巧妙,代码实现起来简单,且时间复杂度仅为O(n)。桶排序的缺点只能对已知数据范围大小的数据进行排序,且当数据很大时需要浪费较大的内存空间,所以运用范围不是很广。下面我们举个例子来说明简化版桶排序:
例:
已知小明的班上有60名学生,现在知道每个同学的语文成绩X[i]
(1<=X[i]
<=100),请你将语文成绩从大到小排序。(本题用以上算法也可做,但比较麻烦)
分析:
既然我们已经知道了待排序元素的大小范围,所以我们可以申请一个容量为101的数组int A[101]={0};
,然后对所有成绩遍历一遍,以成绩X[i]
为数组元素A
的下标,用A[X[i]]++;
记录每个成绩出现的次数。
for(int i=1;i<=60;i++)
A[X[i]]++;
然后我们从大到小输入排序情况:
for(int i=100;i>=1;i--)
while(A[i])
{
A[i]--;
printf("%d ",i);
}
完整代码:
#include<stdio.h>
const int N = 60;//学生数量
int main()
{
int X[N];
int A[101] = { 0 };
for (int i = 0; i < N; i++)
{
scanf("%d", &X[i]);//输入
A[X[i]]++;//统计每个分数出现的次数
}
for(int i=100;i>0;i--)//从大到小输出
while (A[i])
{
A[i]--;
printf("%d ", i);
}
return 0;
}
好了,这就是以上三种排序算法。