一、冒泡排序
(1) 指向数组中两个相邻的元素(最开始是数组的头两个元素),比较它们的大小。
(2) 如果它们的顺序错了(即左边的值大于右边),就互换位置。
如果顺序已经是正确的,那这一步就什么都不用做。
(3) 将两个指针右移一格。
重复第(1)步和第(2)步,直至指针到达数组末尾。
(4)重复第(1)至(3)步,直至从头到尾都无须再做交换,这时数组就排好序了。 这里被重复的第(1)至(3)步是一个轮回,也就是说,这个算法的主要步骤被“轮回”执行, 直到整个数组的顺序正确。
以下是用 Python 写的冒泡排序。
def bubble_sort(list):
unsorted_until_index = len(list) - 1
sorted = False
while not sorted:
sorted = True
for i in range(unsorted_until_index):
if list[i] > list[i + 1]:
sorted = False
list[i], list[i + 1] = list[i + 1], list[i]
unsorted_until_index = unsorted_until_index - 1
list = [65, 55, 45, 35, 25, 15, 10]
bubble_sort(list)
print (list)
执行步骤:比较、交换
在最坏的情况下(即完全反序),需要进行(N - 1) + (N - 2) + (N - 3) + … + 1 次比较。
每次比较后,都要进行一次交换,随着 N 的增长,步数大约增长为 。
因此描述冒泡排序效率的大 O 记法,是 O()。 规范一些来说:用 O( )算法处理 N 个元素,大约需要 步。
二、选择排序
(1) 从左至右检查数组的每个格子,找出值最小的那个。在此过程中,我们会用一个变量来 记住检查过的数字的最小值(事实上记住的是索引,但为了看起来方便,下图就直接写出数值)。 如果一个格子中的数字比记录的最小值还要小,就把变量改成该格子的索引,如图所示。
(2) 知道哪个格子的值最小之后,将该格与本次检查的起点交换。第 1 次检查的起点是索引 0, 第 2 次是索引 1,以此类推。下图展示的是第一次检查后的交换动作。
(3) 重复第(1) (2)步,直至数组排好序。
以下是用 Javascript 写的选择排序。
function selectionSort(array)
{
for (var i = 0; i < array.length(); i++)
{
var lowestNumberIndex = i;
for (var j = i + 1; j < array.length(); j++)
{
if (array[j] < array[lowestNumberIndex])
{
lowestNumberIndex = j;
}
}
if (lowestNumberIndex != i)
{
var temp = array[i];
array[i] = array[lowestNumberIndex];
array[lowestNumberIndex] = temp;
}
}
return array;
}
大 O 记法忽略常数
因此描述选择排序效率的大 O 记法,是 O() 而非 O( / 2)
三、插入排序
(1) 在第一轮里,暂时将索引 1 (第 2 格)的值移走,并用一个临时变量来保存它。这使得该索引处留下一个空隙,因为它不包含值。
在之后的轮回,我们会移走后面索引的值。
(2) 接着便是平移阶段,我们会拿空隙左侧的每一个值与临时变量的值进行比较。 如果空隙左侧的值大于临时变量的值,则将该值右移一格。
随着值右移,空隙会左移。如果遇到比临时变量小的值,或者空隙已经到了数组的最左 端,就结束平移阶段。
(3) 将临时移走的值插入当前空隙。
(4) 重复第(1)至(3)步,直至数组完全有序。
以下是插入排序的 Python 实现。
def insertion_sort(array):
for index in range(1, len(array)):
position = index
temp_value = array[index]
while position > 0 and array[position - 1] > temp_value:
array[position] = array[position - 1]
position = position - 1
array[position] = temp_value
插入排序包含 4 种步骤:移除、比较、平移和插入。
比较的总次数为:1 + 2 + 3 + … + N - 1 次。
temp_value 的移除跟插入在每一轮里都会各发生一次。因为总是有 N - 1 轮,所以可以得出 结论:有 N - 1 次移除和 N - 1 次插入。
我们每次将值右移一格,就是平移操作。当数组完全逆序时,有多少次比较就要多少次平移, 因为每次比较的结果都会使你将值右移。
把最坏情况下的比较步数和平移步数相加。 / 2 次比较 + / 2 次平移 = 步
总共+ 2N - 2 步
大 O 只保留最高阶的 N。
因此描述插入排序效率的大 O 记法,是 O()