2.1 快速排序
class QuickSort:
"""
快速排序
时间复杂度:最坏 O(n*n)、平均 O(n*logn)、最优 O(n*logn)
空间复杂度:最坏 O(n)、平均 O(logn)
简介:
1 找到列表最左边的元素,将其归位,归位后左边元素都比这个元素小,右边元素都比这个元素大
2 归位的元素将列表分为左右两部分,这两部分又可以看成两个新列表,再对这两个新列表递归执行步骤一,直到不能再分
补充:
避免最坏时间复杂度O(n*n):
当列表为有序的情况时,要归位n-1次,效率很低;
可以在递归时,先将首个元素随机和列表中任意元素替换,再对替换后的首位元素归位
"""
@staticmethod
def partition(li, left, right):
"""
在 li[left, right] 中,对left下标元素进行归位
:param li: 无序列表
:param left: 左下标
:param right: 右下标
:return: 归位后的下标
"""
curr = li[left]
while left < right:
while left < right and li[right] >= curr:
right -= 1
li[left] = li[right]
while left < right and li[left] <= curr:
left += 1
li[right] = li[left]
li[left] = curr
return left
def _sort(self, li, left, right):
"""
递归调用归位方法,以实现排序
:param li: 无序列表
:param left: 左下标
:param right: 右下标
:return:
"""
if left < right:
rand = random.randint(left, right)
li[left], li[rand] = li[rand], li[left]
mid = self.partition(li, left, right)
self._sort(li, left, mid - 1)
self._sort(li, mid + 1, right)
def sort(self, li):
"""
快速排序
:param li:
:return:
"""
self._sort(li, 0, len(li) - 1)
return li
2.2 堆排序
class HeapSort:
"""
堆排序
时间复杂度:最坏 O(n*logn)、平均 O(n*logn)、最优 O(n*logn)
空间复杂度:O(1)
简介:
堆结构:一种特殊的完全二叉树结构
大根堆:一个完全二叉树,满足任意节点都比其子节点大
小根堆:一个完全二叉树,满足任意节点都比其子节点小
向下调整特性:
一个非堆结构的完全二叉树,当根结点的左右子树都是堆结构时,可以通过一次向下调整,将其变换成一个堆结构
构建堆:
1 找到最后一个非叶子节点,利用向下调整特性,将其还原成堆结构
2 继续找到上一个非叶子节点,利用向下调整特性,将其还原成堆结构
3 重复步骤2,直到找到最后一个非叶子节点,即跟节点为止,此时构建成堆结构
顺序取堆内的元素:
1 拿出堆顶元素
2 堆尾元素放到堆顶
3 利用向下调整特性,将其还原成一个新的堆
4 重复步骤1,直到数据全部取出
"""
@staticmethod
def sift(li, low, high):
"""
向下调整实现
:param li: 一个非堆结构的完全二叉树,其根结点的左右子树都是堆结构
:param low: 堆的根节点位置
:param high: 堆的最后一个元素的位置
:return:
"""
i = low
j = 2 * i + 1
tmp = li[low]
while j <= high:
if j + 1 <= high and li[j + 1] > li[j]:
j = j + 1
if li[j] > tmp:
li[i] = li[j]
i = j
j = 2 * i + 1
else:
li[i] = tmp
break
else:
li[i] = tmp
def sort(self, li):
"""
堆排序
:param li:
:return:
"""
n = len(li)
for i in range((n - 2) // 2, -1, -1):
self.sift(li, i, n - 1)
for i in range(n - 1, -1, -1):
li[0], li[i] = li[i], li[0]
self.sift(li, 0, i - 1)
return li
2.3 归并排序
class MergeSort:
"""
归并排序
时间复杂度:最坏 O(n*logn)、平均 O(n*logn)、最优 O(n*logn)
空间复杂度:O(n)
简介:
1 递归将列表越分越小,直到分成一个元素,一个即有序
2 递归将两个有序列表归并,列表越来越大
缺点:需要额外内存开销
"""
@staticmethod
def merge(li, low, mid, high):
"""
将两段有序列表归并:列表左段[low, mid],列表右段[mid+1, high]
:param li:
:param low:
:param mid:
:param high:
:return:
"""
curr_list = []
left = low
right = mid + 1
while left <= mid and right <= high:
if li[left] < li[right]:
curr_list.append(li[left])
left += 1
else:
curr_list.append(li[right])
right += 1
while left <= mid:
curr_list.append(li[left])
left += 1
while right <= high:
curr_list.append(li[right])
right += 1
li[low:high + 1] = curr_list
def _sort(self, li, low, high):
"""
递归将列表越分越小,再递归调用归并,最终实现排序
:param li:
:param low:
:param high:
:return:
"""
if low < high:
mid = (low + high) // 2
self._sort(li, low, mid)
self._sort(li, mid + 1, high)
self.merge(li, low, mid, high)
def sort(self, li):
"""
归并排序
:param li:
:return:
"""
self._sort(li, 0, len(li) - 1)
return li