一 算法描述
冒泡排序算法(Bubble Sort)是一种流行但低效的排序算法。它的原理是反复比较待排序数组中所有相邻的两个数据,使他们按照升序(或降序)排列。当待排序数组中所有相邻数据都比较过一次之后,待排序数组中最小(或最大)的数据会被逐步交换到第一位,就像气泡从水底慢慢升到水面一样,故名“冒泡排序算法”。
二 算法实现
1 用于整数数组的升序排序
public static void BubbleSort(int[] array)
{
bool hasExchagend = false;
for (int i = 0; i < array.Length - 1; i++)
{
hasExchagend = false;
for (int j = array.Length - 1; j > i; j--)
{
if (array[j] < array[j - 1])
{
Exchange(ref array[j], ref array[j - 1]);
hasExchagend = true;
}
}
if(!hasExchagend)
{
return;
}
}
}
public static void BubbleDesSort(int[] array)
{
bool hasExchagend = false;
for (int i = 0; i < array.Length - 1; i++)
{
hasExchagend = false;
for (int j = array.Length - 1; j > i; j--)
{
if (array[j] > array[j - 1])
{
Exchange(ref array[j], ref array[j - 1]);
hasExchagend = true;
}
}
if (!hasExchagend)
{
return;
}
}
}
3 泛型版本
public static void BubbleSort(T[] array, Comparison comparison)
{
bool hasExchagend = false;
for (int i = 0; i < array.Length - 1; i++)
{
for (int j = array.Length - 1; j > i; j--)
{
hasExchagend = false;
if (comparison(array[j - 1], array[j]) > 0)
{
Exchange(ref array[j], ref array[j - 1]);
hasExchagend = true;
}
}
if (!hasExchagend)
{
return;
}
}
}
辅助方法
private static void Exchange(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
private static void Exchange(ref T x, ref T y)
{
T temp = x;
x = y;
y = temp;
}
1 此算法中代码为2层嵌套循环,外层循环执行(n-1)次,内层循环平均执行n/2次,故在不考虑代码中return语句的情况下,时间复杂度为O(n^2)。注意到代码中hasExchanged的作用,在开始一轮“冒泡”的时候,hasExchanged置为false,当在完成某一轮“冒泡”后,若hasExchanged仍然为false,则说明本轮冒泡没有进行元素交换,因此原本的待排序数组已经是有序的了,则此时方法直接终止运行并返回。
因此,冒泡算法的最坏情况的时间复杂度为O(n^2),最佳情况下的时间复杂度为O(n).
2 冒泡排序也是一种原址排序算法,所以其空间复杂度为O(1)。
3 冒泡排序算法是稳定的。冒泡排序算法只涉及到相邻两个数据的比较,如果相邻两个数的值相等,并不会发生交换。故,排序前后,相同值的相对位置不会改变。
四 运行结果
在冒泡排序算法中,可根据相邻元素的比较次数来估算。
在算法的泛型实现版本中,通过在委托传入的比较方法里加入计数语句,则能很容易的得到比较语句执行的次数。
private static int AscComparison(int x, int y)
{
count++;
if (x > y)
{
return 1;
}
else if (x == y)
{
return 0;
}
else
{
return -1;
}
}
static void Main(string[] args)
{
for (int i = 0; i < 10000; i++)
{
//在1-100内产生10个随机数
int[] randomIntArray = DataCreator.CreateRandomIntArray(1, 100, 10);
Sort.BubbleSort(randomIntArray, AscComparison);
PrintAarry(randomIntArray);
}
int averageCount = count / 10000;
Console.WriteLine(averageCount);
}
n = 10, averageCount = 32 = 0.32* 10 ^2;
n = 100, averageCount = 3330= 0.33 * 100 ^ 2;
n = 1000, averageCount = 333600 = 0.33 * 1000^2;
可见,冒泡算法的平均时间复杂度也是θ(n^2)