冒泡排序作为所学到的第一个算法,这里对常见的两种方式做简单的总结,总的来说,排序分成了固定最大值和固定最小值两种。
- 固定最大值:每次遍历将所能查找到的最大值放到最末端;
- 固定最小值:每次遍历将所能查找到的最小值放到最首端;
1、固定最大值
该方法的思想是将最大值作为目标,第i次遍历时,将前个数值中最大值放到第个位置。因为第i次遍历时,已经将前个最大的数字放到了最后,所以不用考虑这个数字。假设已有的数组为nums[4] = {9,8,7,6},用下图来表示该方法的步骤:
上图中下标按照C语言的数组下标来,上述步骤可以描述为:
- 第1()次遍历时,可以看到9是这4个数中最大的,那么需要把9放到第4()位;
- 第2()次遍历时,在第一次遍历的基础上,可以知道需要把8放到第3()位;
- 第3()次遍历时,在前两次的基础上,可以知道需要把7放到第2()位;
- 第4次遍历时,排序完成;
上述过程对应的代码为:
for (int i = 0; i < sizeof(nums) / sizeof(nums[0]);i++)//第i次遍历
{
for (int j = 0; j < 9 - i;j++)//限制了第i次遍历需要查看的数字的个数,因为前i-1个数字已经排好
{
if (nums[j] > nums[j + 1])//进行往后走
{
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
2、固定最小值
该方法的思想是将最小值作为目标,第i次遍历时,将后个数值中最小值放到第个位置。因为第i次遍历时,已经将前个最小数字放到了开头,所以不用考虑这个数字。假设已有的数组为nums[4] = {9,8,7,6},用下图来表示该方法的步骤:
上图中下标按照C语言的数组下标来,上述步骤可以描述为:
- 第1()次遍历时,可以看到6是后4()个数中最小的,那么需要把6放到第1位;
- 第2()次遍历时,可以看到7是后3()个数中最小的,那么需要把7放到第2位;
- 第3()次遍历时,可以看到8是后2()个数中最小的,那么需要把8放到第2位;
- 第4次遍历时,排序完成;
上述过程对应的代码为:
for (int i = 0; i < sizeof(nums) / sizeof(nums[0]);i++)//第i次遍历
{
for (int j = i + 1; j < sizeof(nums) / sizeof(nums[0]) - i - 1;j++)
//第i次遍历,将从起始位置到末端这几个数字中最小的放在第i个位置
{
if (a[i] > a[j])//找到更小的就换
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
3、减少时间
可以看到上述的情况是冒泡排序的最差情况,即目标为正序,所有的数字按照倒序来排序。但是若已经排列好的数组例如nums={1,2,3,3}同样需要循环多次,浪费了时间。从上述的两个图中可以看到,只要没有排列好,每次遍历的时候肯定会出现交换数值,那么可以用一个标记来表示是否经过了交换,没有交换可以提前结束。实现代码如下:
bool flag = false;
for (int i = 0; i < sizeof(nums) / sizeof(nums[0]);i++)//第i次遍历
{
for (int j = i + 1; j < sizeof(nums) / sizeof(nums[0]) - i - 1;j++)
//第i次遍历,将从起始位置到末端这几个数字中最小的放在第i个位置
{
if (a[i] > a[j])//找到更小的就换
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
flag = true;
}
}
if(!flag)
break;
}