携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
也是暑假自学python的第15天
排序算法
昨天学习了冒泡排序,选择排序和插入排序,今天开始学习希尔排序,快速排序和堆排序。
希尔排序
缩小增量法,选取n=N,每隔N个为一组,组内进行排序,直到将N缩小到1为止。
希尔排序原理在考研学习的过程中已经熟记于心了,算法也不会用到,就掌握到此。
快速排序
快速排序的核心是分治的思想:找到数组中的一个分割值,将比他小的放在左边,比他大的放在右边。由此分为两个组,再将这两个组的组内进行分治的排序,直到剩下最后一个元素表示排序结束。
设置两个变量i与k,将最后一个数字a首先作为分割值,i与k均从0开始前进。i来遍历数组,k来记录比40小的元素的位置。当遇到一个比a小的数字,交换a[i]和a[k],并且i++,k++。
如果遇到比分割值a大的数字,i++。
如此i全部循环后,表示一趟结束,分割值将数组分为两半,一半小一半大,依次对两部分进行递归。
要写两个方法,第一个:找到分割值最后的位置。第二个:递归
''''
快速排序
'''
def partition(self, left, right):
arr = self.arr
k = left # k始终指向要放置的比分割值小的元素的位置
for i in range(left, right):
if arr[i] < arr[right]:
arr[k], arr[i] = arr[i], arr[k]
k += 1
arr[k], arr[right] = arr[right], arr[k]
return k
第二个递归函数:
def quick(self, left, right):
if left < right:
pivot = self.partition(left, right) # pivot是分割值的下标
self.quick(left, pivot - 1)
self.quick(pivot + 1, right)
堆排序
堆排序再数据结构中的学习也是非常重要,在考研过程中要求掌握手动建堆与排序。
堆排序首先要建堆,然后进行堆调整。
最后一个父亲节点是:n/2-1
左孩子2i,右孩子2i+1
dad=n/2-1
son=2*dad+1
将父亲节点与孩子节点进行比较大小,调整为大根堆与小根堆。不断的对每个父节点进行比较大小并且调整
''''
堆排序
'''
def adjust_max_heap(self, pos, len):
"""
调整某个子树为大根堆
:param pos:调整的子树的父亲
:param len: 整个堆的元素个数
:return:
"""
arr=self.arr
dad=pos
son=2*dad+1
while son<len:
#让左孩子和右孩子比
if son+1<len and arr[son]<arr[son+1]:
son+=1
if arr[son]>arr[dad]: #拿孩子和父亲比,比父亲大,就交换
arr[son],arr[dad]=arr[dad],arr[son]
dad=son
son=2*dad+1
else:
break
大根堆的调整:
def heap(self):
# 下面是把堆调整为大根堆的过程
arr=self.arr
for i in range(self.n // 2 - 1, -1, -1):
self.adjust_max_heap(i, self.n)
arr[0],arr[self.n-1]=arr[self.n-1],arr[0] #交换顶部元素和最后一个元素
for i in range(self.n-1,1,-1):
self.adjust_max_heap(0, i) #把剩余元素调整为大根堆
arr[0], arr[i-1] = arr[i-1], arr[0]
今天学习了三种排序方式。
================================================================