排序算法:
python实现基数排序
python实现归并排序
python实现交换排序
python实现选择排序
python实现插入排序
python实现桶排序
简单选择排序
基本思想:假设排序表为L[1…n],第i趟排序即从L[i…n]中选择关键字最小的的元素与L[i]交换,每一趟排序可以确定一个元素的最终位置,则经过n-1趟排序可以使得整个排序表有序。
def SelectionSort(A):
le=len(A)
for i in range(le):#遍历次数
for j in range(i+1,le):#查找待排序序列中的最小元素并交换
if A[i]>A[j]:
A[i],A[j]=A[j],A[i]
print(A)
tes=[2,4,5,46,34,56,345,34,454]
SelectionSort(tes)#[2, 4, 5, 34, 34, 46, 56, 345, 454]
空间效率:仅使用常数个辅助单元,因此空间效率为O(1)
时间效率:O(n²)
它是一个不稳定的排序算法。
堆排序
堆排序是一种树形选择排序方法,在排序过程中,将L[1…n]看作一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素。
堆的定义:
n个关键字序列L[1…n]称为堆,当且仅当该序列满足:
1)L[i]<=L[2i]且L[i]<=L[2i+1](小根堆)
2) L[i]>=L[2i]且L[i]>=L[2i+1](大根堆)
堆排序的关键是构造初始堆,对初始序列建堆,就是一个反复筛选的过程。n个结点的完全二叉树,最后一个结点是n//2个节点的孩子。对n//2个节点为根的子树筛选(对于大根堆,若根结点的关键字小鱼左右子女中关键字较大者,则交换),使该子树成为堆。之后向前依次对各节点(n//2~1)为根的子树进行筛选,看该结点是否大于其左右子节点的值,若不是,则将左右子结点中较大值与之交换,交换后可能会破坏下一级的堆,于是继续采用上述方法构造下一级的堆,直到以该结点为根的子树构成堆为止。
同时,堆也支持删除和插入操作。由于堆顶元素为最大值或者最小值,删除堆顶元素时,先将堆的最后一个元素与堆顶元素交换,由于此时堆得性质被破坏,需对此时的根结点进行向下调整操作。
对堆进行插入操作时,先将新结点放在堆的末端,再对这个结点执行向上调整操作。
大根堆排序(Heap Sort)
一种基于堆的排序算法,它利用了堆数据结构的特性来实现排序。大根堆是一种满足堆属性的完全二叉树,即每个节点的值都大于等于其子节点的值。
算法逻辑:
1.构建大根堆:将待排序数组看作是一个完全二叉树,从最后一个非叶子节点开始,依次向上调整使得每个子树都满足大根堆的性质。这个过程称为“堆化(Heapify)”。
2.调整大根堆:重复进行以下操作,直到所有节点都满足大根堆的性质:
3.将根节点与最后一个节点交换位置,即将最大值移到数组末尾。
4.缩小堆的范围(即排除最后一个节点),并对根节点进行一次“下沉”操作,使得根节点重新满足大根堆的性质。
堆排序:通过不断地进行步骤2,直到堆的大小减小到1,最终得到一个有序的数组。
# 实现一个最大堆
class MaxHeap(object):
"""
实现一个大顶堆
"""
def __init__(self):
self.array = [] # 用一个数组存放堆中元素
def heapify(self, array):
"""
对传入的数组进行堆化
"""
for a in array:
self.push(a)
return self.array
def get_size(self):
"""
返回堆的大小
"""
return len(self.array)
def _parent(self, index):
"""
返回某个节点的父节点
"""
if index == 0:
raise Exception('Index 0 has no parent')
return int((index - 1) / 2)
def _left_child(self, index):
"""
返回左孩子节点的索引
"""
return index * 2 + 1
def _right_child(self, index):
"""
返回右边孩子节点的索引
"""
return index * 2 + 2
def _shift_up(self, k):
"""
节点上移动,将当前节点与其父亲节点比较大小,如果比父亲节点大,
则交换其位置,重复只执行上述过程,直到当前节点比父亲节点小。
"""
while k > 0 and self.array[self._parent(k)] < self.array[k]:
# 交换节点与父节点的值
self.array[self._parent(k)], self.array[k] = self.array[k], self.array[self._parent(k)]
k = self._parent(k)
def _shift_down(self, k):
"""
节点下移动, 当前节点与它左右孩子中最大的节点交换位置
"""
while self._left_child(k) < self.get_size():
choose_index = self._left_child(k) # 左孩子的索引
# 先比较左右孩子的大小,选择较大的那个孩子再与父亲节点进行比较
if choose_index + 1 < self.get_size() and self.array[choose_index + 1] > self.array[choose_index]:
choose_index = self._right_child(k)
if self.array[choose_index] <= self.array[k]: # 如果最大的孩子比父亲节点小,退出循环
break
# 否则父亲节点和最大的子节点交换位置
self.array[choose_index], self.array[k] = self.array[k], self.array[choose_index]
k = choose_index # 进行下次循环
def push(self, value):
"""
添加一个元素后,需要对堆重新进行堆化,具体过程就是对堆尾元素执行上移操作;
"""
self.array.append(value)
self._shift_up(self.get_size() - 1) # 相当于对堆进行重新堆化
def pop(self):
"""
返回堆顶元素,将堆顶元素和堆最后一个元素交换,
然后返回最后一个元素,最后对堆顶元素进行下沉操作(重新堆化)
"""
ret = self.find_max()
self.array[0], self.array[self.get_size() - 1] = self.array[self.get_size() - 1], self.array[0]
self.array.pop(-1) # 删除最后一个元素
self._shift_down(0)
return ret
def find_max(self):
"""
查看堆中的最大值
"""
if self.array:
return self.array[0]
else:
raise Exception('Empty heap has no value')
# 测试我们实现的大顶堆
test = [12, 11, 10, 9, 6, 7, 8, 13]
max_heap = MaxHeap()
print(max_heap.heapify(test)) # 对一个数组执行堆化
print(max_heap.pop()) # 弹出堆顶元素
print(max_heap.array)
max_heap.push(14) # 推入一个元素
print(max_heap.array)
空间效率:仅使用常数个辅助单元,因此空间效率为O(1)
时间效率:O(nlog2 N)
它是一种不稳定的排序算法
小根堆排序算法(Min Heap Sort)
一种基于堆的排序算法,它通过构建小根堆(每个节点的值都小于或等于其子节点的值)来进行排序。其基本逻辑是:
1.将待排序的数组构建成一个小根堆。
2.不断从堆顶(即根节点)取出最小值,并将其与堆的最后一个元素交换,然后调整堆,使其保持小根堆的性质。
3.重复步骤2,直到堆中的元素全部取出,得到有序的数组。
def min_heapify(arr, n, i):
smallest = i
left_child = 2 * i + 1
right_child = 2 * i + 2
if left_child < n and arr[left_child] < arr[smallest]:
smallest = left_child
if right_child < n and arr[right_child] < arr[smallest]:
smallest = right_child
if smallest != i:
arr[i], arr[smallest] = arr[smallest], arr[i]
min_heapify(arr, n, smallest)
def build_min_heap(arr):
n = len(arr)
for i in range(n // 2 - 1, -1, -1):
min_heapify(arr, n, i)
def heap_sort(arr):
n = len(arr)
build_min_heap(arr)
for i in range(n - 1, 0, -1):
arr[0], arr[i] = arr[i], arr[0]
min_heapify(arr, i, 0)
# 测试
arr = [12, 11, 13, 5, 6, 7]
heap_sort(arr)
print("排序后的数组:", arr)
算法逻辑讲解:
min_heapify函数:用于维护小根堆的性质,假设数组中第i个元素的左子节点索引为2i+1,右子节点索引为2i+2。在min_heapify函数中,首先找到当前节点与其左右子节点中的最小值,并记录最小值的索引,然后将当前节点与最小值交换位置,接着递归调整以最小值为根节点的子树,使其满足小根堆的性质。
build_min_heap函数:用于构建初始的小根堆。从数组的中间位置开始,依次对每个非叶子节点调用min_heapify函数,使得整个数组构成一个小根堆。
heap_sort函数:排序的核心逻辑,首先构建初始的小根堆,然后不断将堆顶(最小值)与堆的最后一个元素交换位置,并调整堆,直到整个数组有序。