排序算法
1.排序的定义:假设含有n个记录的序列为{r1,r2,……,rn},其相应的关键字分别为{k1,k2,……,kn},需确定 1,2,……,n的一种排列p1,p2,……,pn,使其相应的关键字满足kp1≤kp2≤……≤kpn(非递减或非递增)关系,即使得序列成为一个按关键字有序的序列{rp1,rp2,……,rpn},这样的操作就称为排序。
2.常用术语:稳定与不稳定
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
3.常用术语:内排序与外排序
内排序:所有排序操作都在内存中完成;
外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
4.排序算法的性能三大影响因素
(1) 时间性能(时间复杂度): 一个算法执行所耗费的时间。
(2)辅助空间 (空间复杂度):运行完一个程序所需内存的大小。
(3) 算法的复杂性 : 算法本身的复杂度,而不是指算法的时间复杂度
5.各种排序算法不同的时间复杂度
6.不同排序算法的内存占用情况
交换排序:冒泡排序
1.定义:冒泡排序(Bubble Sort)一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端。
2.冒泡排序算法的运作如下:
(1).比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
(2).对每一对相邻元素作同样的工作,从开始第一对到结尾最后一对,这步做完后,最后的元素会是最大的数。
(3)针对所有的元素重复以上的步骤,除了最后一个。
(4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
例:
原始数组:5 2 2 8 3
第一趟排序:2 2 5 3 8
第二趟排序:2 2 3 5 8
第三趟排序:2 2 3 5 8
3.冒泡排序的特点:
最好的情况,也就是要排序的表本身就是有序的,那么我们比较次数,可以推断出就是
n‐1 次的比较,没有数据交换,时间复杂度为O(n)。
最坏的情况,即待排序表是逆序的情况,此时需要比较1+2+3+4+......+(n-1)=n(n-1)/2次,
即时间复杂度为O(n**2)。
稳定性: 稳定
交换排序:快速排序
1.快速排序的基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则课分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
层数为O(logn)(即调用栈的高度为O(logn)),而每层需要的时间为O(n)。因此整个算法需要的时间为O(n) * O(logn) = O(nlogn)
代码实现部分:
def quicksort(array):
if len(array) < 2:
return array #基线条件:为空或只包含一个元素的数组是有序的
else:
pivot = array[0] #递归条件
less = [i for i in array[1:] if i <= pivot] #由所有小于基准值的元素组成的子数组
greater = [i for i in array[1:] if i > pivot] #由所有大与基准值的元素组成的子数组
return quicksort(less) + [pivot] + quicksort(greater)
print(quicksort([28,2,1,27,15,9]))
插入排序:直接插入排序
直接插入排序的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。
插入排序示意图:
直接插入排序代码实现:
def insert_sort(nums):
count = len(nums)
for i in range(1, count):
key = nums[i]
j = i - 1
while j >= 0:
if nums[j] > key:
nums[j + 1] = nums[j]
nums[j] = key
j -= 1
return nums
if __name__ == '__main__':
nums = [3,2,7,5,1,9,6,8,0]
sort_nums = insert_sort(nums)
print(sort_nums)
直接插入排序原理:每次将排序中的元素,插入到前面已经排好序的有序序列中去,直到排序完成。
步骤:
第一步,a[0]为有序区,待排序区为a[1…n-1]。令i=1。
第二步,将a[1]与a[0]中元素比较,将小的元素放在第一个位置。
第三步,以此类推,直到待排序中全部元素插入完成为止。
最好的情况,也就是要排序的表本身就是有序的, 因此没有移动的记录,时间复杂
度为 O(n)。
最坏的情况,即待排序表是逆序的情况,时间复杂度为 O(n**2)。
直接插入排序:希尔排序
希尔排序是D.L.Shell于 1959 年提出来的一种排序算法,在这之前排序算法的时间复杂度基本
都是O(n2)的,希尔排序算法是突破这个时间复杂度的第一批算法之一。
希尔排序基本思想:
算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的然后
再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行
直接插入排序后,排序完成。
选择排序
定义:选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。