例子场景
还是使用lesson1中的例子,这次我们使用冒泡排序来实现。
代码实现
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n=5; //n=5表示有5个数字需要排序
int score[5] = {5,3,5,2,8};
int i, j, k;
//冒泡排序的核心部分
for(i=0; i<n-1; i++) { //一盘
for(j=0; j<n-i; j++) { //一局
if(score[j]<score[j+1]) { //降序
k = score[j];
score[j] = score[j+1];
score[j+1] = k;
}
}
}
for(i=0; i<n; i++) {
printf("%d \n", score[i]);
}
return 0;
}
算法分析
冒泡排序的基本思想是:每次比较两个相邻的元素,如果他们的顺序错误,就把他们交换过来。
冒泡排序的代码实现中,核心代码是第10行和第11行的双重for循环。你可以把外层的for循环想象成网球比赛中的一盘,而内层的for循环想象成网球比赛中的一局。
第一盘i=0
- 第一局j=0; 第一个元素与第二个元素进行比较,如果顺序错误,则交换过来。
- 第二局j=1;第二个元素与第三个元素进行比较,如果顺序错误,则交换过来。
- ……
- 第n-1局j=n-1;第n-1个元素与第n个元素进行比较,如果顺序错误,则交换过来。
- 第一盘的结果(假设使用降序排序): 数组中最后一个元素的值被确定:score[n] = 最小的分数。
第二盘i=1
- 第一局j=0; 第一个元素与第二个元素进行比较,如果顺序错误,则交换过来。
- 第二局j=1;第二个元素与第三个元素进行比较,如果顺序错误,则交换过来。
- ……
- 第n-2局j=n-2;第n-2个元素与第n-1个元素进行比较,如果顺序错误,则交换过来。
- 第二盘的结果(假设使用降序排序): 数组中倒数第二个元素的值被确定:score[n-1] = 倒数第二小的分数。
以此类推,当第5盘i=4完成后,数组中的第一个元素的值也被确定了: score[0] = 最大的分数。
时间复杂度
冒泡排序的时间复杂度主要用双层for循环确定。在上面的例子中,一共执行了4+3+2+1 = 5*(5-1)/2 = 10次。即N*(N-1)/2 = (N*N-1)/2。忽略较小常数后可知,冒泡排序的时间复杂度为O(N*N)。
优点缺点
冒泡排序是一种用时间换空间的排序方法。它占用的空间比较小,但是时间复杂度非常高,因此在实际开发中很少使用。