(1)几种最经典、最常用的排序方法:冒泡排序、插入排序、选择排序、快速排序、归并排序、计数排序、基数排序、桶排序。
(2)复杂度归类
冒泡、插入、选择 O(n^2) 基于比较
快排、归并 O(nlogn) 基于比较
计数、基数、桶 O(n) 不基于比较
1)冒泡排序只会操作相邻的两个数据。
2)对相邻两个数据进行比较,看是否满足大小关系要求,若不满足让它俩互换。
3)一次冒泡会让至少一个元素移动到它应该在的位置,重复n-1次,就完成了n个数据的排序工作。
4)优化:若某次冒泡不存在数据交换,则说明已经达到完全有序,所以终止冒泡。
def bubble_sort(collection):
"""冒泡排序"""
length = len(collection)
for i in range(length-1): # 只要冒泡length-1轮就可以排好序
swapped = False # 记录是否发生交换
for j in range(length-1-i):
if collection[j] > collection[j+1]:
swapped = True
collection[j], collection[j+1] = collection[j+1], collection[j]
if not swapped: # 没有发生交换,说明已经排好序
break
return collection
if __name__ == '__main__':
collection = list(map(int, input().split()))
print('排序前:', end='')
for i in collection:
print(i, end=' ')
collection = bubble_sort(collection)
print('\n排序后:', end='')
for i in collection:
print(i, end=' ')
1)执行效率:最好时间复杂度、最坏时间复杂度、平均时间复杂度
最好时间复杂度:数据完全有序时,只需进行一次冒泡操作即可,时间复杂度是O(n)。
最坏时间复杂度:数据倒序排序时,需要n次冒泡操作,时间复杂度是O(n^2)。
平均时间复杂度:通过有序度和逆序度来分析,时间复杂度是O(n^2)。
2)空间复杂度:每次交换仅需1个临时变量,故空间复杂度为O(1),是原地排序算法。
3)算法稳定性:如果两个值相等,就不会交换位置,故是稳定排序算法。
插入排序将数组数据分成已排序区间和未排序区间。初始已排序区间只有一个元素,即数组第一个元素。在未排序区间取出一个元素插入到已排序区间的合适位置,直到未排序区间为空。
def insertion_sort(collection):
"""插入排序"""
length = len(collection)
for i in range(1, length): # 第一个数作为初始有序序列,所以不用比较
j = i - 1
while j >= 0 and collection[j + 1] < collection[j]:
collection[j], collection[j + 1] = collection[j + 1], collection[j]
j -= 1
return collection
def insertion_sort2(collection):
"""插入排序"""
length = len(collection)
for i in range(1, length): # 第一个数作为初始有序序列,所以不用比较
j = i - 1
tmp = collection[i]
while j >= 0 and collection[j] > tmp: # 插入合适的位置
collection[j + 1] = collection[j]
j -= 1
collection[j+1] = tmp
return collection
if __name__ == '__main__':
collection = list(map(int, input().split()))
print('排序前是:', end='')
for i in collection:
print(i, end=' ')
collection = insertion_sort2(collection)
print('\n排序后是:', end='')
for i in collection:
print(i, end=' ')
1)执行效率:最好时间复杂度、最坏时间复杂度、平均时间复杂度
最好时间复杂度:数据完全有序时,只需进行一次冒泡操作即可,时间复杂度是O(n)。
最坏时间复杂度:数据倒序排序时,时间复杂度是O(n^2),往数组中插入一个数的平均时间复杂度是O(n),一共重复n次。
平均时间复杂度:通过有序度和逆序度来分析,时间复杂度是O(n^2)。
2)空间复杂度:每次交换仅需1个临时变量,故空间复杂度为O(1),是原地排序算法。
3)算法稳定性:如果两个值相等,就不会交换位置,故是稳定排序算法。
选择排序将数组分成已排序区间和未排序区间。初始已排序区间为空。每次从未排序区间中选出最小的元素插入已排序区间的末尾,直到未排序区间为空。
def selection_sort(collecion):
"""选择排序"""
length = len(collection)
for i in range(length -1): # 比较length-1轮就可以排好序
least = i # 保存每轮比较中的最小数
for j in range(i+1, length):
if collection[j] < collection[least]:
least = j
collection[i], collection[least] = collection[least], collection[i]
return collection
if __name__ == '__main__':
collection = list(map(int, input().split()))
print('排序前:', end='')
for i in collection:
print(i, end=' ')
collection = selection_sort(collection)
print('\n排序后:', end='')
for i in collection:
print(i, end=' ')
1)执行效率:最好时间复杂度、最坏时间复杂度、平均时间复杂度
最好时间复杂度、最坏时间复杂度、平均时间复杂度都是O(n^2)。
2)空间复杂度:每次交换仅需1个临时变量,故空间复杂度为O(1),是原地排序算法。
3)算法稳定性:如果两个值相等,就可能会交换位置,故是不稳定的排序算法。
// 冒泡排序中数据的交换操作:
if (a[j] > a[j+1]) { // 交换
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
flag = true;
}
// 插入排序中数据的移动操作:
if (a[j] > value) {
a[j+1] = a[j]; // 数据移动
} else {
break;
}
本文章是学习王争老师在极客时间专栏——《数据结构与算法之美》的学习总结,文章很多内容直接引用了专栏下的回复,推荐大家购买王争老师的专栏进行更加详细的学习
。本文仅供学习使用,勿作他用,如侵犯权益,请联系我,立即删除。