10.排序
阅读目录:
一.冒泡排序
代码示例: 时间复杂度O(n2) n的平方,如果排序的列表之后没有进行变动,则不需要再进行交换,直接退出函数即可
def bubble_shot_l(li):
for i in range(len(li)-1): 共N-1趟
change= False
for j in range(len(li)-i-1): #相当于每一趟的指针
if li[j]>li[j+1]:
li[j],li[j+1]=li[j+1],li[j]
change = True
if not change:
return
li = [1,4,5,0,3,9,8,6]
bubble_shot_l(li)
print(li)
二.选择排序
- 选择排序改进了冒泡排序,每次遍历列表只做一次交换。为了做到这一点,一个选择排序在他遍历时寻找最大的值,并在完成遍历后,将其放置在正确的位置。
def selectionSort(alist): for i in range(len(alist)-1,0,-1): positionOfMax=0 for location in range(1,i+1): if alist[location]>alist[positionOfMax]: positionOfMax = location temp = alist[i] alist[i] = alist[positionOfMax] alist[positionOfMax] = temp alist = [54,26,93,17,77,31,44,55,20] selectionSort(alist) print(alist)
def select_shot(l): for i in range(len(l)-1): #对于L这个列表需要走6趟 min_flag = i #设置一个最小索引值 for j in range(i+1,len(l)): #需要让列表中的每个元素进行对比 if l[j] < l[min_flag]: #如果无序列表小于有序列表中l[min_flag] min_flag = j #则把最小索引进行交换 if min_flag != i : #如果最小索引不等于有序列表中的i l[i],l[min_flag]=l[min_flag],l[i] #对其进行值交换 l=[5,2,4,6,7,8,3] select_shot(l) print(l)
- 对于冒泡排序来讲选择排序由于交换数量的减少,选择排序通常在基准研究中执行得更快。
三.插入排序
- 插入排序的主要思想是每次取一个列表元素与列表中已经排序好的列表段进行比较,然后插入从而得到新的排序好的列表段,最终获得排序好的列表。比如,待排序列表为[49,38,65,97,76,13,27,49],则比较的步骤和得到的新列表如下:(带有背景颜色的列表段是已经排序好的,红色背景标记的是执行插入并且进行过交换的元素)
def insert_sort(alist): for j in range(1, len(alist)): i = j while i > 0: if alist[i] < alist[i - 1]: alist[i], alist[i - 1] = alist[i - 1], alist[i] i -= 1 else: break return alist alist = [3,8,5,7,6] print(insert_sort(alist))
def insert_shot(l): for i in range(1,len(l)): #表示摸到的牌的下标 tmp = l[i] j = i-1 #表示手里牌的下标 while j>=0 and l[j]>tmp: l[j+1]=l[j] j-=1 l[j+1]=tmp l = [2,1,3,5,6,4,8] insert_shot(l) print(l)
四.希尔排序
- 希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本,该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量(gap)”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高。
def shell_sort(alist): n = len(alist) gap = n//2 while gap >= 1: #插入排序 for j in range(gap,n): i = j while i > 0: # i > gap if alist[i] < alist[i-gap]: alist[i],alist[i-gap] = alist[i-gap],alist[i] i -= gap else: break #缩短gap的步长 gap //= 2 alist = [3,8,5,7,6] shell_sort(alist) print(alist)
五.归并排序
- 归并排序采用分而治之的原理:
- 将一个序列从中间位置分成两个序列;
- 在将这两个子序列按照第一步继续二分下去;
- 直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。
- 如何合并?
下图中的倒数第三行表示为第一次合并后的数据。其中一组数据为 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))
六.快速排序 O (nlogn)
def quiteSort(alist,start,end): low = start height = end if low >= height: return 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 alist[low] = mid quiteSort(alist,start,low-1) quiteSort(alist,low+1,end) l = [3,8,5,7,6] quiteSort(l,0,len(l)-1) print(l)