前言 |
算法的学习已经进行了好几次了,每一次的理解都是一知半解,但感觉自己懂了,核心代码都可以倒背如流,其实只是对几行代码的记忆,并非真正的去理解了,在这次的学习中保持一个特别端正的态度去学习,每一个算法都做到理解-思考-实践-讲解-思考,真正的懂得算法的奥妙!
概念 |
冒泡排序是一个较简单的排序算法原理如下(升序):
1. 比较相邻的元素,。如果第一个比第二个大,两两交换。
2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3. 针对所有元素重复以上的步骤,除了最后一个。
4. 持续每次对越来越少的元素重复上面的步骤,知道没有任何一对数字需要比较。
详解 |
条件:升序。
数组:4 9 3 5 7
排序过程:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/655a06ce49f14b943e8c1ef2816175ce.png)
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/094f2989839f6605e230165215b8a1ae.png)
拓展 |
以上是对冒泡的实现的拆分,通过对i、j循环过程中的次数的分析可以得出核心代码如下:
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = 0; j < arr.Length - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
冒泡的核心代码是在交换处,这个很容易理解,但是两个for循环有时会不清晰。上面的举例最终形成了一个左下三角(如上图蓝色三角)。这是建立在每次都选择出最大的值,使右侧形成一个有序区,那可不可以在左侧形成有序区呢?当然可以,如下:
#region 第二种情况
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = arr.Length - 1; j > i; j--)
{
if (arr[j - 1] > arr[j])
{
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
#endregion
注意这两种方法的不同之处在什么地方,我们发现:
①for循环中j的条件变了。
②核心代码的下标值形式发生了变化。
这是因为排序最主要的一个条件发生了变化,每次选出每一行的最小值,所以需要相应的条件发生变化。这个过程通过分解步骤是很容易理解的。当我做完这两种情况的时候,我发现两个循环的条件还可以进行变换,我就推出了下面两种情况:
#region 第三种情况
for (int i = arr.Length - 1; i > 0; i--)
{
for (int j = 0; j < i; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
#endregion
#region 第四种情况
for (int i = arr.Length - 1; i > 0; i--)
{
for (int j = i; j >0; j--)
{
if (arr[j - 1] > arr[j])
{
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
#endregion
这两种情况,我没有去通过详细的步骤得到的,是通过推导得出的,如果有疑惑或者问题欢迎随时联系我~