目录
1.冒泡排序
1.1原理
1.2时间复杂度和空间复杂度:
参考文章
时间复杂度:
这个时间复杂度还是很好计算的:外循环和内循环以及判断和交换元素的时间开销;
最优的情况也就是开始就已经排序好序了,那么就可以不用交换元素了,则时间花销为:[ n(n-1) ] / 2;所以最优的情况时间复杂度为:O( n^2 );
最差的情况也就是开始的时候元素是逆序的,那么每一次排序都要交换两个元素,则时间花销为:[ 3n(n-1) ] / 2;(其中比上面最优的情况所花的时间就是在于交换元素的三个步骤);所以最差的情况下时间复杂度为:O( n^2 );
综上所述:
最优的时间复杂度为:O( n^2 ) ;有的说 O(n),下面会分析这种情况;
最差的时间复杂度为:O( n^2 );
平均的时间复杂度为:O( n^2 );
空间复杂度:
空间复杂度就是在交换元素时那个临时变量所占的内存空间;
最优的空间复杂度就是开始元素顺序已经排好了,则空间复杂度为:0;
最差的空间复杂度就是开始元素逆序排序了,则空间复杂度为:O(n);
平均的空间复杂度为:O(1);
1.3python实现:
def bubble_sort(items):
for i in range(len(items) - 1):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
return items
list1 = [2,1,9,11,10,8,7]
print(bubble_sort(list1))
2.快速排序
2.1原理
参考文章
最差情况的快速排序退化成冒泡排序。
2.2python实现(递归):
def sub_sort(array, low, high):
pivotkey = array[low]
while low < high:
while low < high and array[high] >= pivotkey:
high -= 1
array[low] = array[high]
while low < high and array[low] <= pivotkey:
low += 1
array[high] = array[low]
array[low] = pivotkey
return low
def quick_sort(array, low, high):
if low >= high:
return
if low < high:
pivoloc = sub_sort(array, low, high)
quick_sort(array, low, pivoloc - 1)
quick_sort(array, pivoloc + 1, high)
if __name__ == "__main__":
array = [49, 38, 65, 97, 76, 13, 27]
print(array)
quick_sort(array, 0, len(array) - 1)
print(array)
3.归并排序
牺牲空间实现时间。对于单向链表,归并排序的复杂度较低。
3.1原理
3.2复杂度
时间复杂度:
这个图显然是二叉树的形式,所以若集合有n个元素,那高度就为log(n)
但其实在每一层做比较的时候,都是一个一个的向序列中放小的元素,每一层都是要放n次
所以时间复杂度为nlog(n)
3.3 python实现:
参考文章:
def merge(s1,s2,s):
"""将两个列表是s1,s2按顺序融合为一个列表s,s为原列表"""
# j和i就相当于两个指向的位置,i指s1,j指s2
i = j = 0
while i+j<len(s):
# j==len(s2)时说明s2走完了,或者s1没走完并且s1中该位置是最小的
if j==len(s2) or (i<len(s1) and s1[i]<s2[j]):
s[i+j] = s1[i]
i += 1
else:
s[i+j] = s2[j]
j += 1
def merge_sort(s):
"""归并排序"""
n = len(s)
# 剩一个或没有直接返回,不用排序
if n < 2:
return
# 拆分
mid = n // 2
s1 = s[0:mid]
s2 = s[mid:n]
# 子序列递归调用排序
merge_sort(s1)
merge_sort(s2)
# 合并
merge(s1,s2,s)
if __name__ == '__main__':
s = [1,7,3,5,4]
merge_sort(s)
print(s)
4.插入排序
4.1原理
参考文章
插入排序原理很简单,将一组数据分成两组,我分别将其称为有序组与待插入组。每次从待插入组中取出一个元素,与有序组的元素进行比较,并找到合适的位置,将该元素插到有序组当中。就这样,每次插入一个元素,有序组增加,待插入组减少。直到待插入组元素个数为0。当然,插入过程中涉及到了元素的移动。
为了排序方便,我们一般将数据第一个元素视为有序组,其他均为待插入组。
下面以升序为例进行一次图解:
4.2复杂度
两层循环:n^2。
对于有的文章说n^2/2,算复杂度要去掉不重要成分,这里系数1/2就是不重要成分。
4.3python实现
def insertSort(arr):
length = len(arr)
for i in range(1,length):
x = arr[i]
for j in range(i,-1,-1):
# j为当前位置,试探j-1位置
if x < arr[j-1]:
arr[j] = arr[j-1]
else:
# 位置确定为j
break
arr[j] = x
arr = [4, 7 ,8 ,2 ,3 ,5]
insertSort(arr)
print(arr)
5.选择排序
5.1原理
5.2复杂度
选择排序的时间复杂度为:O(n^2),空间复杂度:O(1)
选择排序是不稳定的;
5.3python实现
def getmin(arr):
min = arr[0];
min_index = 0;
for i in range(0,len(arr)):
if arr[i]<min:
min = arr[i]
min_index = i
return min_index
#SelectSort
def selectSort(arr):
newArr = [];
for i in range(0,len(arr)):
min = getmin(arr);
newArr.append(arr.pop(min))
return newArr;
#test the output
a = [4,6,9,1,3,87,41,5]
print(selectSort(a))