冒泡排序
1. 冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
2. 冒泡排序算法的原理如下:
1) 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2) 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3) 针对所有的元素重复以上的步骤,除了最后一个。
4) 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
def sort(alist):
length = len(alist)
for j in range(0, length -1):
for i in range(0, length-1-j):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
alist = [8,5,6,9,2,3]
sort(alist)
print(alist)
选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
对于冒泡排序来讲选择排序由于交换数量的减少,选择排序通常在基准研究中执行得更快。
def sort(alist):
length = len(alist)
for j in range(length-1, 0, -1):
# 最大值元素的下标
max_index = 0
for i in range(1, j+1):
if alist[max_index] < alist[i]:
max_index = i
# 每次遍历完将最大的数放在较后位置依次排列
alist[max_index], alist[j] = alist[j], alist[max_index]
插入排序
插入排序的主要思想是每次取一个列表元素与列表中已经排序好的列表段进行比较,然后插入从而得到新的排序好的列表段,最终获得排序好的列表。比如,待排序列表为[49,38,65,97,76,13,27,49],则比较的步骤和得到的新列表如下:(带有背景颜色的列表段是已经排序好的,红色背景标记的是执行插入并且进行过交换的元素)
def sort(alist):
length = len(alist)
for j in range(1, length):
i = j # i 就是无序列表中的第一个元素
while i > 0:
if alist[i] < alist[i-1]:
alist[i],alist[i-1] = alist[i-1],alist[i]
i -= 1
else:
break
希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本,该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量(gap)”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高。
def sort(alist):
gap = len(alist) // 2
while gap >= 1:
for j in range(gap,len(alist)):
i = j
while i > 0:
if alist[i] < alist[i-gap]:
alist[i],alist[i-gap] = alist[i-gap],alist[i]
i -= gap
else:
break
gap = gap // 2
快速排序
1. 基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
2. 算法描述
1) 先从序列中取出一个数作为基准数
2) 分区过程, 将比这个数大的数全部放到它的右边, 小于或等于它的数全部放到它的左边
3) 再对左右区间重复第二步, 直到各区间只有一个数
假设对 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 进行排序, 首先在这个序列中随便找一个基准数(用来参照), 比如选择 6 为基准数, 接下来把所有比基准数大的数放在6的右边, 比6小的数放在左边
3. 原理分析:
1) 选择最左边的数为基准数key
2) 设立两个游标 low 和 high , 分别指向数组的最低位和最高位
3) 然后high先动, 如果high位上的数比key大, 则向前走, 如果high-1位上的数比key大, 继续向前走, 直到该位上的数<=key
4) 此时比较low位, 如果<=key, low向后走, 变为low+1, 依次类推, 直到该位上的数比key大
5) 交换high和low位上的数
6) 重复以上步骤, 直到low=high , 交换 key 和 high 位上的值
7) 最后进行递归操作
def quickSort(alist,start,end):
low = start
height = end
# 判断low是否大于height, 如果为True,直接返回
if low >= height:
return
# 设置一个比较基准的 key
mid = alist[low]
while low < height:
# 从右往左进行判断
while low < height:
if alist[height] >= mid:
height -= 1
else:
alist[low] = alist[height]
break
while low < height:
if alist[low] < mid:
low += 1
else:
alist[height] = alist[low]
break
# 做完第一轮比较之后,列表被分成了两个半区,并且i=j,需要将这个数设置回mid
alist[low] = mid
quickSort(alist,start,low-1)
quickSort(alist,low+1,end)
l = [3, 8, 5, 7, 6, 2, 0, 4, 1, 9]
quickSort(l,0,len(l)-1)
print(l)
归并排序
1. 归并排序采用分而治之的原理:
- 将一个序列从中间位置分成两个序列;
- 在将这两个子序列按照第一步继续二分下去;
- 直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。
2. 如何合并?
下图中的倒数第三行表示为第一次合并后的数据。其中一组数据为 4 8 , 5 7。该两组数据合并方式为:每一小组数据中指定一个指针,指针指向每小组数据的第一个元素,通过指针的偏移指定数据进行有序排列。排列如下:
1) p1指向4,p2指向5,p1和p2指向的元素4和5进行比较,较小的数据归并到一个新的列表中。经过比较p1指向的4会被添加到新的列表中,则p1向后偏移一位,指向了8,p2不变。
2) p1和p2指向的元素8,5继续比较,则p2指向的5较小,添加到新列表中,p2向后偏移一位,指向了7。
3) p1和p2指向的元素8,7继续比较,7添加到新列表中,p2偏移指向NULL,比较结束。
4) 最后剩下的指针指向的数据(包含该指针指向数据后面所有的数据)直接添加到新列表中即可。
def merge_sort(alist):
n = len(alist)
# 结束递归的条件
if n <= 1:
return alist
# 中间索引
mid = n//2
left_li = merge_sort(alist[:mid])
right_li = merge_sort(alist[mid:])
# 指向左右表中第一个元素的指针
left_pointer,right_pointer = 0,0
# 合并数据对应的列表:该表中存储的为排序后的数据
result = []
while left_pointer < len(left_li) and right_pointer < len(right_li):
# 比较最小集合中的元素,将最小元素添加到result列表中
if left_li[left_pointer] < right_li[right_pointer]:
result.append(left_li[left_pointer])
left_pointer += 1
else:
result.append(right_li[right_pointer])
right_pointer += 1
# 当左右表的某一个表的指针偏移到末尾的时候,比较大小结束,将另一张表中的数据(有序)添加到result中
result += left_li[left_pointer:]
result += right_li[right_pointer:]
return result
alist = [3,8,5,7,6]
print(merge_sort(alist))