1. 冒泡排序:
- 原理
冒泡排序算法的基本原理就是比较相邻两个数字的大小。将两个数中比较大的那个数交换到靠后的位置,不断交换下去就可以将最大的那两个数放到队列的尾部。然后重头再次交换)(交换list.lenght-1次),直到将数列排成有序数列。
- 代码实现
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def bubbleSort(List):
"""
冒泡排序
:param List:
:return:
"""
if len(List) <= 1:
return List
for i in range(len(List)-1): # 经过n-1轮排序
for j in range(len(List)-1): # 比较前一个数和后一个数的大小关系
if List[j] >= List[j+1]:
List[j], List[j+1] = List[j+1], List[j] # 如果前一个数比后一个数大,则调换位置
return List
if __name__ == '__main__':
print(List)
print(bubbleSort(List))
runtime = timeit.timeit("bubbleSort(List)","from __main__ import bubbleSort, List",number=1000)
print(runtime)
2. 选择排序:
- 原理
简单来说,选择排序只做了一件事件,那就是从数列中选择最大(最小)的那个数,将这个数放到合适的位置。然后抛开这个数的子序列中找最大(最小)的那个数放到合适的位置。然后一直到子序列为空。
- 代码实现
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
"""
# 这个虽简洁易懂,但有重复数字会有有Bug,原因为相同数下标无法确定
def selectSort(List):
if len(List) <= 1: # 如果长度小于等于1,直接返回
return List
for i in range(0, len(List)-1): # 遍历数组
if List[i] >= min(List[i+1:]): # 如果对应下标数的值大于剩余部分的最小值,交换位置
minIndex = List.index(min(List[i+1:])) # 求剩余部分的最小值小标
List[i], List[minIndex] = List[minIndex], List[i] #满足条件, 交换位置
return List
"""
def selectSort(List):
if len(List) <= 1: # 如果长度小于等于1,直接返回
return List
for i in range(len(List)-1):
min_index = i
for j in range(i+1,len(List)):
if List[j] < List[min_index]:
min_index = j
List[i], List[min_index] = List[min_index], List[i]
return List
if __name__ == '__main__':
print(List)
print(selectSort(List))
print(timeit('selectSort(List)','from __main__ import selectSort, List',number=1000))
3. 插入排序:
- 原理
插入排序首先将数列分为两部分,数列的第一数为left,其余数位right部分。然后将right部分中的数逐一取出,插入到left部分的适当位置。当right部分为空时,left部分就成了一个有序的序列。
- 代码实现
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def insertSort(List):
if len(List) <= 1:
return List
for right in range(1,len(List)): # 遍历右边没有排序的数组
target = List[right] # 需要排序的值
for left in range(0, right):
if target <= List[left]:
List[left+1:right+1] = List[left:right] # 将左边已经排序好的数组整体右移一位
List[left] = target # 将需排序的值到左边已排序好数组的适当位置
break # 提高性能,如果比边已排序好的最小数都小,一次则跳出循环
return List
# 第二种思路,从左边排序的列表最后边向最左边比较
def insertSort2(List):
if len(List) <= 1:
return List
for i in range(1,len(List)):
j = i
while j > 0:
if List[j] < List[j-1]:
List[j], List[j-1] = List[j-1], List[j]
j -= 1
else:
break
return List
if __name__ == '__main__':
print(List)
print(insertSort(List))
print(timeit('insertSort(List)','from __main__ import insertSort, List',number=1000))
4. 快速排序:
- 原理
以列表中任意一个数为基准(一般选用列表的第一个数,因为递归调用的最后每个列表只有一个数),将列表分为左右两个子列表:左边子列表的数要比基准数小,右边子序列表的数要比基准数打。然后继续把左边子列表和右边子列表按照同样的方法继续分解、比较,一直到无法分解为止。然后按照左边子列表(比基准数小) + 基准数 + 右边子列表(比基准数大)的方式连接起来。最后合成了一个有序数列。
- 代码实现
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def quickSort(List):
"""
快速排序:优点:代码简洁,易于理解 缺点: 太过耗费空间
:param List:
:return:
"""
if len(List) <= 1:
return List
left = [] # 左区,用来存放比基准数小的数
right = [] # 右区,用来存放比基准数大的数
for i in List[1:]: # 遍历除基准数以外的所有数
if i <= List[0]:
left.append(i)
else:
right.append(i)
return quickSort(left) + [List[0]] + quickSort(right) # 递归调用,无限拆分后合并各个有序数组
if __name__ == '__main__':
print(List)
print(quickSort(List))
print(timeit('quickSort(List)','from __main__ import quickSort, List',number=1000))
5. 哈希排序
- 原理
改进了得插入排序,将待排序的数组根据差量分成若干的的子数组,分别进行插入排序,通过不断地修改组距,使得分组数逐渐减少,当组距为1是,则就是一个插入排序
- 代码实现
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def shellSort(List):
"""
希尔排序
:param List:
:return:
"""
n = len(List)
gap = n // 2
# gap变化到0之前,插入算法执行的次数
while gap > 0:
# 插入算法,与普通的插入算法的区别就是gap步长
for i in range(gap, n): # 外层循环控制的是所有子序列的所有元素(不包括每一组第一个数)
j = i
while j > 0:
if List[j] < List[j - gap]: # 内层循环就是一个插入排序,比较与前一个数的大小关系
List[j], List[j - gap] = List[j - gap], List[j]
j -= gap
else:
break
# 缩短gap步长
gap //= 2
return List
if __name__ == '__main__':
print(List)
print(shellSort(List))
print(timeit('shellSort(List)','from __main__ import shellSort, List',number=1000))
6. 计数排序
- 原理
计数排序算法采用了一个巧妙的办法,首先需要创建一个与原数列等长的新数列,选择一个数为计基数,然后统计整个数列中有多少个数比基数小。如果有n个数比基数小,那么将基础放到数列的n+1位置上(不过此方法的空间和时间复杂度都比较大)
- 代码实现
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def countingSort(List):
"""
计数排序
:param List:
:return:
"""
if len(List) <= 1:
return List
# 创建一个跟原数组长度相同的空数组
rLen = len(List)
rList = [None]*rLen
for i in range(rLen): # 遍历数组,选择基数
small = 0 # 记录比基数小的个数
same = 0 # 记录跟基数相等的个数
for j in range(rLen): # 找出比基数小或相等的数
if List[j] < List[i]:
small += 1
elif List[j] == List[i]:
same += 1
for k in range(small,small+same):
rList[k] = List[i]
return rList
if __name__ == '__main__':
print(List)
print(countingSort(List))
print(timeit('countingSort(List)','from __main__ import countingSort, List',number=1000))