|—使用堆实现优先队列:
对于总共N个请求 使用普通数组或者顺序数组 最差情况O(N^2)
使用堆 O(N*Log N)
|-堆的基本实现
二叉堆:任何一个子节点都不大于他的父节点
必须是一棵完全二叉树
用数组存储二叉堆:
|-shift up
|-shift down
|-基础堆排序
heapSort1
|-heapify 堆排序
建堆的过程直接构建 不用挨个元素插入
新建一个堆的构造函数 , 传入一个数组arr 和 该数组长度n
|-原地堆排序
堆的索引从数组下标0开始
无需额外的空间
parent(i) = (i-1)/2
left child(i) = 2*i +1
对于总共N个请求 使用普通数组或者顺序数组 最差情况O(N^2)
使用堆 O(N*Log N)
|-堆的基本实现
二叉堆:任何一个子节点都不大于他的父节点
必须是一棵完全二叉树
用数组存储二叉堆:
|-shift up
|-shift down
|-基础堆排序
heapSort1
|-heapify 堆排序
建堆的过程直接构建 不用挨个元素插入
新建一个堆的构造函数 , 传入一个数组arr 和 该数组长度n
|-原地堆排序
堆的索引从数组下标0开始
无需额外的空间
parent(i) = (i-1)/2
left child(i) = 2*i +1
right child(i) = 2*i +2
源代码:
https://github.com/lzneu/Algrithm_python
import random
import numpy as np
import datetime
def genNearlyOrderArray(n, swapTimes):
arr = list(range(n))
for i in range(swapTimes):
x = random.randint(0, n)
y = random.randint(0, n)
swap(arr, x, y)
return arr
def genRandomArray(n, start=0, end=10000):
return np.random.randint(start, end, size=n)
def aTestSort(sortName, arr, n):
t_start = datetime.datetime.now()
sortName(arr, n)
t_end = datetime.datetime.now() # 记录函数结束时间)
long = (t_end - t_start).total_seconds()
if isSorted(arr, n):
print("sortName: %s, time: %f s" % (sortName.__name__, long))
else:
print('Sort ERROR!')
def swap(arr, i, j):
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
def isSorted(arr, n):
for i in range(n - 1):
if (arr[i] > arr[i + 1]):
return False
return True
from tools import *
import sorting_advanced
class MaxHeap:
def __init__(self):
self.__data = [0]
self.__count = 0
# 构造函数 给定一个数组创建一个最大堆 时间复杂度O(n)
def buildHeap(self, arr):
n = len(arr)
self.__count = n
self.__data = [0]
self.__data.extend(arr)
for i in range(n // 2):
index = n // 2 - i
self.__shiftDown(index)
def size(self):
return self.__count
def isEmpty(self):
return self.__count == 0
def __swap(self, i, j):
temp = self.__data[i]
self.__data[i] = self.__data[j]
self.__data[j] = temp
# 最大堆核心辅助函数
def __shiftUp(self, k):
while (k > 1) and (self.__data[(k // 2)] < self.__data[k]):
self.__swap(k // 2, k)
k = k // 2
def insert(self, item):
self.__data.append(item)
self.__count += 1
self.__shiftUp(self.__count)
def __shiftDown(self, k):
# 判断有无左孩子
while (2 * k <= self.__count):
j = 2 * k # 在此轮循环中 data[k] 与 data[j] 交换位置
if (j + 1 <= self.__count and self.__data[j + 1] > self.__data[j]):
j += 1
if (self.__data[k] >= self.__data[j]):
break
self.__swap(k, j)
k = j
# 从队中去除堆顶元素 即堆中所存储的最大元素
def extractMax(self):
if self.__count <= 0:
raise IndexError
ret = self.__data[1]
self.__swap(1, self.__count)
self.__data.pop(self.__count)
self.__count -= 1
self.__shiftDown(1)
return ret
def heapSort1(arr, n):
maxHeap = MaxHeap()
for i in range(n):
maxHeap.insert(arr[i])
for i in range(n):
index = n - 1 - i
arr[index] = maxHeap.extractMax()
def heapSort2(arr, n):
maxHeap = MaxHeap()
maxHeap.buildHeap(arr)
for i in range(n):
index = n - 1 - i
arr[index] = maxHeap.extractMax()
def __shiftDown2(arr, n, k):
temp = arr[k]
# 判断有无孩子
while (2 * k + 1 <= n - 1):
j = 2 * k + 1
if j + 1 < n and arr[j + 1] > arr[j]:
j += 1
if temp >= arr[j]:
break
arr[k] = arr[j]
k = j
arr[k] = temp
# 原地堆排序
def heapSort(arr, n):
# 从最后一个非叶子节点开始 n-1-1 // 2
for i in range((n - 1 - 1) // 2, -1, -1):
__shiftDown2(arr, n, i)
for i in range(n - 1, 0, -1):
swap(arr, i, 0)
__shiftDown2(arr, i, 0)
if __name__ == '__main__':
# # 测试堆的数据结构
# maxHeap = MaxHeap()
# print(maxHeap.size())
# for i in range(50):
# a = random.randint(0, 100)
# maxHeap.insert(a)
# # print(a)
#
# while(maxHeap.size() != 0):
# num = maxHeap.extractMax()
# print(num)
n = 100000
start = 0
end = 100000
# arr = genNearlyOrderArray(n, swapTimes=100)
arr = genRandomArray(n, start, end)
arr2 = arr.copy()
arr3 = arr.copy()
arr4 = arr.copy()
arr5 = arr.copy()
aTestSort(heapSort1, arr, n)
aTestSort(heapSort2, arr2, n)
aTestSort(sorting_advanced.quickSort2, arr3, n)
aTestSort(sorting_advanced.quickSort3Ways, arr4, n)
aTestSort(heapSort, arr5, n)