前提
对还不算入门的小白,关于算法这一部分更是理解甚少,只是记得老师曾讲过用三角形表示冒泡排序算法方法,面对那个三角形更是迷迷糊糊的样子,真是迷惑了好久,最近看关于泛型内容讲解的知识刚好遇到这一部分内容。花了点时间终于觉得自己搞了哈。(PS:以下内容如有不对还希望读者指出,不胜感激。)
何为冒泡排序法?
无论是怎样排序,排在下面的沉底,然排在前面的数据上浮。例如从大到小排序,思想就是小数沉底,大数上浮。关于这个算法参加比较的两个元素是相临的,每轮比较可以找出一个本轮中最小的放到本轮最后,使所有的大数向前移位置。
代码展示:
#region 冒泡排序法测试 ——— 贾文静 2016年5月5日17:50:08
static void Main(string[] args)
{
SortHelper sorter = new SortHelper();
int[] array = { 7, 1, 4, 8, 3 };
sorter.BubbleSort(array);
foreach (int i in array)
{
Console.Write("{0} ", i);
}
Console.ReadKey();
}
#endregion
#region SortHelper封装的冒泡排序的算法 ——贾文静 2016年5月5日17:51:36
public class SortHelper
{
public void BubbleSort(int[] array)
{
//获取数组中数据的个数
int length = array.Length;
//外层循环
for (int i = 1; i <= length - 1; i++)
{
//内层循环,j=0 是因为C#中数组默认元素从0开始
for (int j = 0; j <= length - 1 - i; j++)
{
if (array[j] < array[j + 1])
{
//移动过程
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
#endregion
运行结果:
用图形表示
老师讲课的时候用的是一个三角形,并且和选择排序算法进行了比较,这次展示冒泡,关于选择下篇文章展示。自己研究的时候比较迷惑,搞不懂这个三角到底怎么画,原因忽略了坐标轴。如果坐标轴不确定,怎么画怎么都对!
复杂度
关于这个图还是自己亲自动手试试比较,写出来的内容远比脑子中想象来的更具体一些。在讲着算法排序的时候有提到时间复杂度,而且百度百科中也有这一部分的内容。在讲解这一部分内容的时候提到了两个概念时间复杂度和空间复杂度。
时间复杂度
比较次数:用C表示Compare
移动次数:用M表示Move
当正序的时候,一趟扫描即可完成排序,比较为n-1;移动次数为0
当反序的时候,需要进行n-1趟排序。每趟排序要进行n-1次关键字的比较,比较次数为n(n-1)/2,移动次数为3n(n-1)/2
即为 Cmax = n(n-1)/2 = O(n2)
Mmax = 3n(n-1)/2 = O(n¬2)
为什么这样算
先算比较次数,首先看代码中的这一部分:
for (int i = 1; i <= length - 1; i++)
{
//内层循环,j=0 是因为C#中数组默认元素从0开始
for (int j = 0; j <= length - 1 - i; j++)
{
if (array[j] < array[j + 1])
{
//移动过程
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
外层的循环次数是固定的n-1,但是内层循环的次数按序依次减少的,最多的时候为n-1,直到最后一次为1,按照梯形的面积算法 (n-1+1)*(n-1)/2 则为n(n-1)/2,每一次比较都需要移动三次,即
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
所以移动次数为:3n(n-1)/2
时间复杂度又是怎样计算的?
对于n位的数列则有比较次数为 (n-1) + (n-2) + … + 1 = n * (n - 1) / 2,这就得到了最大的比较次数而O(N^2)表示的是复杂度的数量级。举个例子来说,如果n = 10000,那么 n(n-1)/2 = (n^2 - n) / 2 = (100000000 - 10000) / 2,相对10^8来说,10000小的可以忽略不计了,所以总计算次数约为0.5 * N^2。用O(N^2)就表示了其数量级(忽略前面系数0.5)
空间复杂度
从实现原理可知,冒泡排序是在原输入数组上进行比较交换的(称“就地排序”),所需开辟的辅助空间跟输入数组规模无关,所以空间复杂度为:O(1)
特点
优点:冒泡排序是稳定的,不会改变相同元素的相对顺序,每次比较都是两两比较,涉及数据范围小。
缺点:看时间复杂度就知道了,也正是因为每次只能移动两个数据,而且涉及到循环的嵌套使用起来,比较慢。如果真的在大程序中时候运行速度就是不能想象啊。
总结
关于这个冒泡排序只是简单的基本算法之一,这是通过总结尝试用图去描述算法使用,但是图是很简单,前提是自己明白图的由来,否则一切都是白费。虽然冒泡很简单,但是时间运算上的速度,还是非常值得优化,关于后面的部分正在学习中,学习以后再进行分享。
PS:话说自己没有去总结之前,每次想到这就是困恼,搞不懂图为什么要这样画,这次终于解除这样的负罪感了啊。