终于搞明白堆排序了,汗一个
先上代码:
def heapify(a, idx, size)
left_idx = 2 * idx + 1
right_idx = 2 * idx + 2
bigger_idx = idx
bigger_idx = left_idx if left_idx < size && a[left_idx] > a[idx]
bigger_idx = right_idx if right_idx < size && a[right_idx] > a[bigger_idx]
if bigger_idx != idx
a[idx], a[bigger_idx] = a[bigger_idx], a[idx]
heapify(a, bigger_idx, size)
end
end
def build_heap(a)
last_parent_idx = a.length / 2 - 1
i = last_parent_idx
while i >= 0
heapify(a, i, a.size)
i = i - 1
end
end
def heap_sort(a)
return a if a.size <= 1
size = a.size
build_heap(a)
while size > 0
a[0], a[size-1] = a[size-1], a[0]
size = size - 1
heapify(a, 0, size)
end
return a
end
a = [1,5,3,6,4,3,2,7,9,0,8,0,10]
p heap_sort(a)
算法原理:
利用二叉树,先将一个数组构建成一个“最大堆”,保证对每个节点i,它的相邻子节点left和right都<=i
这时根节点就是最大的数,将它和最后一个节点互换位置
然后从根节点开始与相邻的子节点比较大小,如果left或right比它大,则互换位置,称为“下移”,直到第n-1个节点,这一轮“下移”之后根节点成为除了最后一个节点之外最大的数,将它和倒数第二个节点互换位置
。。。
循环直到所有节点做完“下移”操作,这时数组已经从小到大排好序了
关键:
有两点:
1,先构建“最大堆”,从最后一个节点的父节点开始做“下移”,直到根节点
2,每次“下移”结束后不能将最大值根节点从数组中删除,只能跟最后一个节点互换位置,这样是为了保证二叉树的结构不变,即还是一个“最大堆”,所以堆排序又称为“in place sort”
时间复杂度:
一个长度为n的数组,用二叉树来表示的话共有lgn层
对节点i,比较它相邻的left节点和right节点并做“下移”操作的时间为Θ(1)
可以用数学归纳法来证明heapsort的时间复杂度为Θ(nlogn)
1,初始化构建“最大堆”的时间为O(nlgn),不影响结果(实际上为O(n))
2,可以知道对n=3,6,f(n) < nlgn,
而f(2n) = f(n) + nlg(2n)
< nlgn + n(1+lgn)
= 2nlgn + n
< 2n(lgn + 1)
= 2nlg2n
所以fn = Θ(nlgn)
分享到:
相关推荐
1. **排序算法**:包括冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序等。Go语言中的切片和并发特性使得这些排序算法的实现既直观又高效。 2. **搜索算法**:如二分查找、广度优先搜索(BFS)和深度优先...
2. 快速排序、归并排序、堆排序:高效排序算法,平均时间复杂度为O(n log n)。 3. 二分查找:在有序数组中查找元素,时间复杂度为O(log n)。 4. 搜索树:二叉搜索树、AVL树和红黑树等,用于快速查找、插入和删除操作...
CLRS 最后,要拿 LeetCode,Python 可以让你专注于想法,而 CLRS 真的有点乏味,所以每当你读完时,你就会感到很高兴,因为你可以做 LeetCode。 :books: :open_book: :pencil: :notebook: :hamburger: :spaghetti: :...
CLRS教材练习算法关于该项目重点在于通过在代码中实现对基本和高级数据结构及算法的掌握。 这主要是在Python中完成的。促成主题分叉项目创建功能分支( git checkout -b feature/AmazingFeature ) 提交更改( git ...
6. **图论算法**:最小生成树(Prim和Kruskal算法)、最短路径(Dijkstra算法和Floyd-Warshall算法)、拓扑排序。 7. **回溯与分支限界**:用于解决组合优化问题,如八皇后问题、旅行商问题。 8. **概率算法与随机...
1. **排序算法**:如快速排序(Quicksort)、归并排序(Merge Sort)、堆排序(Heap Sort)、插入排序(Insertion Sort)、选择排序(Selection Sort)等。这些算法在处理大量数据时非常关键,它们的不同特性决定了...
- **第6章:堆排序** - **6.1 堆**:定义了堆数据结构,并讨论了其基本性质。 - **6.2 维护堆属性**:介绍了如何在堆操作中保持堆的性质不变。 #### 五、总结 《算法导论》第三版是一本经典且全面的算法教材,...
- **第6章:堆排序** - 详细介绍堆排序算法的工作原理及其时间复杂度分析。 - **第7章:快速排序** - 深入分析快速排序算法,并讨论其在不同场景下的应用。 - **第8章:线性时间排序** - 探讨几种可以在线性时间内...
CLRS英文第二版 .
2. **排序与搜索算法**:快速排序、归并排序、堆排序、插入排序、选择排序、冒泡排序、二分查找、哈希表查找等。C++中,`std::sort`函数提供了排序功能,而`std::lower_bound`和`std::upper_bound`则用于区间查找。 ...
第6章:堆排序 - **讲义**:详细介绍堆排序的工作原理及其实现步骤。 - **解答**:分析堆排序算法的时间复杂度,并提供实际操作的代码示例。 ##### 6. 第7章:快速排序 - **讲义**:阐述快速排序的基本思想、分区...
一个个人帮助页面,用于准备数据结构和算法,重点是CLRS书籍... /src目录是添加各种算法的实现的位置。 该README.md文件用于列出数据结构和算法,而不一定来自本书。 快速浏览 目录 Sl。 话题 1。 :check_box_...
1. **排序算法**:CLRS中介绍了多种排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序等。Python中的`sorted()`函数和`list.sort()`方法可以轻松实现这些排序,但理解它们的内部工作原理对于...
大名鼎鼎的 CLRS Algorithm Introduction 算法导论 课后大部分的题目解答
这些字符可以理解为观测序列的一部分,而后面的数字序列\( 1 6 5 4 3 2 \)则可以视为状态集的一部分。结合Viterbi算法的基本思想,我们需要根据这些输入来计算出最可能的状态序列。 具体实现过程中,我们首先需要...
算法导论 CLRS Mit Press - Introduction To Algorithms 2Nd Edition Incl Exercises Edition.chm