排序算法原理
冒泡排序(Bubble Sort)的原理简述如下:
(以倒排、升序为例)
1.选出数组中未排序部分,从后向前将相邻两个元素比较,使较小的换至索引值小的位置,循环操作即可将最小值换至首位;
2.更新数组的未排序部分,重复以上操作即可完成排序。
代码示例
此处以c#代码为例,其他语言大同小异(转换为所需语言请看<语法说明>板块以作参考)
·简单示例
public static void BubbleSort(int[] nums)
{
//未排序部分为[i,nums.Length - 1]
for (int i = 0; i < nums.Length - 1; i++)
{
//比较出未排序部分的最小值,与第一个值交换
for (int j = nums.Length - 1; j > i; j--)
{
if (nums[j - 1] > nums[j])
Swap(nums, j, j - 1);
}
}
}
// 交换数组中的两个值
private static void Swap<T>(T[] arr, int i, int j)
{
(arr[i], arr[j]) = (arr[j], arr[i]);
}
考虑到如果某轮冒泡未执行任何交换操作,则说明排序已经完成,则可直接结束,因此做出以下优化:
public static void BubbleSort(int[] nums)
{
for (int i = 0; i < nums.Length - 1; i++)
{
//如果某轮冒泡未执行任何交换操作,则说明排序已经完成,则可直接结束
bool flag = false;
for (int j = nums.Length - 1; j > i; j--)
{
if (nums[j - 1] > nums[j])
{
Swap(nums, j, j - 1);
flag = true;
}
}
if (!flag) break;
}
}
·进阶用法
public static void BubbleSort<T>(T[] arr, Func<T, T, bool> func)
{
for (int i = 0; i < arr.Length - 1; i++)
{
bool flag = false;
for (int j = arr.Length - 1; j > i; j--)
{
if (func(arr[j - 1], arr[j]))
{
Swap(arr, j, j - 1);
flag = true;
}
}
if (!flag) break;
}
}
语法说明
为便于其他语言使用者进行代码转换,此处对可能存在的语法疑问作出注解。
1.public表示该函数是公开的,可根据具体语言及需求调整;
2.static表示该函数是静态的,可根据具体语言及需求调整;
3.void表示该函数返回值为空,可根据具体语言调整;
4.int是表示Int32类型的关键字,意为4个字节的有符号整形;
5.bool是表示Boolean类型的关键字,值为true或false;
6.for循环的语法结构为:
for(初始化索引;保持循环的条件;每次循环结束执行的语句){循环体}
这与C,C++,Java,Go,JS,TS,Dart类似。在Python,Swift,Rust中可替换为for index in range结构。
break关键字在for循环中起到跳出循环的作用。
7.方法名<T>的写法表示泛型,有些语言也称作参数多态或模板;
8.Func<T, T, bool> func的写法表示委托,相当于Java的接口和匿名内部类;Python的函数指针、高阶函数和回调函数;JS的回调函数和事件处理程序;Swift的代理等。在示例代码中,意为将一个函数作为参数传入,该函数需要两个类型为T的参数,并有一个bool类型的返回值。
算法特性
时间复杂度O(n)到O(n²):算法中采用了双层循环嵌套,最差的情况下为O(n²),但由于我们通过flag进行了优化,则有可能达到O(n);
空间复杂度O(1):仅对原数组进行操作。