1.概念
- 排序:所谓排序,即将本无序的序列重新排列成有序序列的过程。
- 稳定性:指当待排排序序列有两个或两个以上相同的关键字时,排序前和排序后这些关键字的相对位置,如果没有发生变化,就是稳定的,否则就是不稳定的。
2.分类
- 插入类排序 --插入(直接插入排序、折半插入排序、希尔排序)
- 交换类排序–交换(冒泡排序、快速排序)
- 选择类排序–选择(简单选择排序、堆排序)
- 归并类排序–归并(二路归并排序)
- 基数类排序–多关键字(基数排序)
3.插入类排序
3.1 直接插入排序
-
算法思想
每趟将一个待排序的关键字按照其值的大小插入到已经排好的部分有序序列的适当位置上,直到所有待排关键字都被插入到有序序列中为止。 -
代码实现
# 插入排序 from __future__ import print_function def insertion_sort(collection): """ :param collection: :return: collection """ for loop_index in range(1, len(collection)): insertion_index = loop_index # 哨兵 while insertion_index > 0 and collection[insertion_index - 1] > collection[insertion_index]: collection[insertion_index], collection[insertion_index - 1] = \ collection[insertion_index - 1], collection[insertion_index] insertion_index -= 1 return collection if __name__ == '__main__': try: raw_input except NameError: raw_input = input user_input = raw_input('请输入数字用","隔开:\n').strip() unsorted = [int(item) for item in user_input.split(',')] print(insertion_sort(unsorted))
-
性能分析
算法复杂度:
最坏:逆序,复杂度为O(n^2)
最好:正序,复杂度为O(n)
平均:O(n^2)空间复杂度:
O(1)稳定性:
稳定
3.2 折半插入排序
-
算法思想
-
代码实现
-
性能分析
算法复杂度:
最坏:
最好:
平均:空间复杂度:
稳定性:
3.3 希尔排序
-
算法思想
-
代码实现
-
性能分析
算法复杂度:
最坏:
最好:
平均:空间复杂度:
稳定性:
4.交换类排序
4.1 冒泡排序
-
算法思想
-
代码实现
-
性能分析
算法复杂度:
最坏:
最好:
平均:空间复杂度:
稳定性:
4.2 快速排序
-
算法思想
每一趟选择当前子序列中的一个关键字作为枢轴,将子序列中比枢轴小的移到枢轴前边,比枢轴大的一道枢轴后边;当本趟所有子序列都划分完毕,会得到一组更短的子序列,它们成为下一趟划分的初始序列集。 -
代码实现
def quick_sort(R, low, high): """ 快速排序 :param R: 待排序列 :param low: 序列小下标 :param high: 序列大下标 :return: 已排序序列 """ i, j = low, high # 两个指针 if low < high: # 序列有意义时 temp = R[low] # 选择第一个为枢轴 while i < j: # 一轮循环结束标志 while j > i and R[j] >= temp: # 从右往左扫描,找到一个小于temp的关键字 j = j - 1 if i < j: R[i] = R[j] # 把这个 较小数放到 左边,注意temp被覆盖了,j所指数有两个 i = i + 1 while i < j and R[i] < temp: # 从左往右扫描,找到一个大于temp的关键字 i = i + 1 if i < j: R[j] = R[i] # 注意,测试 j 所指原位置上的数被覆盖 j = j - 1 R[i] = temp # 将 temp放到最终位置 quick_sort(R, low, i-1) # 对左边 快排 quick_sort(R, i+1, high) # 对右边快排 return R if __name__ == '__main__': user_input = input('Enter numbers separated by a comma:\n').strip() unsorted = [int(item) for item in user_input.split(',')] print(quick_sort(unsorted, 0, len(unsorted) - 1))
测试:
Enter numbers separated by a comma:
6,7,4,2,8,1,9,3,10,5
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -
性能分析
算法复杂度:
最坏:有序,O(n^2)
最好:无序,O(logn)
平均:O(logn)空间复杂度:
O(logn)稳定性:
稳定
5.选择类排序
5.1 简单选择排序
-
算法思想
从头到尾顺序扫描序列,找出最小的一个关键字,和第一个关键字交换,接着从剩下的关键字中继续这种选择和交换。 -
代码实现
def select_sort(R): """ 选择排序 :param R: 待排序列 :return: 已排序序列 """ temp = 0 for i in range(len(R)): k = i for j in range(i+1, len(R)): if R[k] > R[j]: k = j R[i], R[k] = R[k], R[i] return R if __name__ == '__main__': user_input = input('Enter numbers separated by a comma:\n').strip() unsorted = [int(item) for item in user_input.split(',')] print(select_sort(unsorted))
-
性能分析
算法复杂度:
O(n^2)空间复杂度:
O(1)稳定性:
5.2 堆排序
-
算法思想
堆:堆是一颗完全二叉树,满足:任何一个非叶结点的值都不大于(或不小于)其左右孩子结点的值。若父亲大,孩子小,叫大顶堆,否则叫小顶堆。
堆排序就是构造一个堆,根节点值是最大(小)的,然后将这个值交换到序列的最后(前),这样,有序关键字加1,无序关键字减1。
关键操作,调整为堆。 -
代码实现
def heapify(unsorted, index, heap_size): largest = index left_index = 2 * index + 1 right_index = 2 * index + 2 if left_index < heap_size and unsorted[left_index] > unsorted[largest]: largest = left_index if right_index < heap_size and unsorted[right_index] > unsorted[largest]: largest = right_index if largest != index: unsorted[largest], unsorted[index] = unsorted[index], unsorted[largest] heapify(unsorted, largest, heap_size) def heap_sort(unsorted): n = len(unsorted) for i in range(n // 2 - 1, -1, -1): heapify(unsorted, i, n) for i in range(n - 1, 0, -1): unsorted[0], unsorted[i] = unsorted[i], unsorted[0] heapify(unsorted, 0, i) return unsorted if __name__ == '__main__': user_input = input('Enter numbers separated by a comma:\n').strip() unsorted = [int(item) for item in user_input.split(',')] print(heap_sort(unsorted))
-
性能分析
算法复杂度:
nlogn空间复杂度:
O(1)稳定性:
不稳定
5. 归并类排序、基数排序
5.1 归并排序
-
算法思想
-
代码实现
-
性能分析
算法复杂度:
最坏:
最好:
平均:空间复杂度:
稳定性:
5.2 基数排序
-
算法思想
-
代码实现
-
性能分析
算法复杂度:
最坏:
最好:
平均:空间复杂度:
稳定性:
6. 其他排序
6.1
-
算法思想
-
代码实现
-
性能分析
算法复杂度:
最坏:
最好:
平均:空间复杂度:
稳定性: