堆分类是借助一种称为堆的完全二元树结构进行的。完全二元树可以用一个数组表示。在这种表示法中,容易确定一个结点的父结点及其左右儿子的下标。现在,把具有如下性质的数组A表示的完全二元树称为堆:(1)如果2i < n, 则A[i] <= A[2i] (2)如果2i + 1 < n, 则A[i] <= A[2i + 1] 。即树中任一非叶子结点的值都不大于其左右儿子结点的值。
堆排序算法思想:(1)初始化操作:初始建堆(2)每一趟排序的基本操作:将堆中的第一个结点值与最后一个结点值交换,重新把前面的元素整理成堆。
我的方法实现与这种略有差别:我是每次先整理成堆,然后交换。
其实都是一样的,都是以一个堆开始,以交换结束。
/**
* 堆排序类
*
* @author YouFengkai
*
*/
public class HeapSort {
private final int ARRAYSIZE = 10;
// 该数组表示一颗完全二叉树
private int[] tree;
public HeapSort() {
// 排序下标1到ARRAYSIZE的
this.tree = new int[ARRAYSIZE + 1];
for (int i = 0; i < this.ARRAYSIZE + 1; i++) {
tree[i] = (int) (1 + Math.random() * 40);
}
}
// 输出排序数组下标1到ARRAYSIZE中的所有数据
public void desc() {
for (int i = 1; i <= ARRAYSIZE; i++) {
System.out.print(tree[i]);
System.out.print(" ");
}
System.out.println();
}
// 堆排序
public void sort() {
int last = ARRAYSIZE;
for (int i = last; i >= 2; i--) {
// 初始化堆,先整理好堆,从i/2开始是因为这是最后一个非叶子结点
for (int j = i / 2; j >= 1; j--) {
pushDown(j, i);
}
// 树根为最小的,把它与最后的元素交换。
// 除最后的元素外,是一个只有树根不满足条件的堆,重新整理。
swap(1, i);
}
}
/**
* 交换树中两个节点的值
*
* @param positionA
* 第一个位置
* @param positionB
* 第二个位置
*/
private void swap(int positionA, int positionB) {
int temp = tree[positionA];
tree[positionA] = tree[positionB];
tree[positionB] = temp;
}
/**
* 下推整理堆
*
* @param first
* 开始整理的第一个节点
* @param last
* 最大的节点
*/
private void pushDown(int first, int last) {
// 如果first位置不是叶子节点,开始下推整理
int r = first;
if (r <= last / 2) {
// 如果当前节点不是叶子,则继续整理下推
while (2 * r <= last) {
int leftSon = 2 * r;
boolean hasRightSon = false;
int rightSon = leftSon + 1;
if (leftSon + 1 <= last) {
hasRightSon = true;
}
// 如果只有左儿子,且左儿子值比当前节点值小,则与左儿子交换
if (!hasRightSon && tree[leftSon] < tree[r]) {
swap(r, leftSon);
r = leftSon;
}
// 否则如果右儿子值不大于左儿子值,且左儿子值比当前节点值小,则与左儿子交换
else if (hasRightSon && tree[rightSon] <= tree[leftSon]
&& tree[rightSon] < tree[r]) {
swap(r, rightSon);
r = rightSon;
}
// 否则如果左儿子值不大于右儿子值,且左儿子值比当前节点值小,则与左儿子交换
else if (hasRightSon && tree[leftSon] <= tree[rightSon]
&& tree[leftSon] < tree[r]) {
swap(r, leftSon);
r = leftSon;
}
// 否则,不做变化。结束循环
else {
break;
}
}
} else {
return;
}
}
public static void main(String[] args) {
HeapSort hs = new HeapSort();
System.out.println("初始的数组为:");
hs.desc();
hs.sort();
System.out.println("经过堆排序后的数组为:");
hs.desc();
}
}
结果:
初始的数组为:
22 36 18 10 24 18 12 35 15 5
经过堆排序后的数组为:
36 35 24 22 18 18 15 12 10 5
分享到:
相关推荐
堆排序:应用Java和Python分别实现堆排序算法; 堆排序:应用Java和Python分别实现堆排序算法; 堆排序:应用Java和Python分别实现堆排序算法; 堆排序:应用Java和Python分别实现堆排序算法; 堆排序:应用Java和...
一个堆排序算法 c++写的 逻辑相同 可自行 改为java 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一...
本话题主要探讨六种内部排序算法:直接插入排序、希尔排序、冒泡排序、快速排序、选择排序以及堆排序。这六种排序算法各有优劣,适用于不同的场景,接下来我们将逐一进行详细阐述。 1. **直接插入排序**: 直接...
堆排序是一种基于比较的排序算法,它利用了数据结构中的“堆”这一概念。在计算机科学中,堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。堆排序有两种...
快速排序是C++中最常用的排序算法之一,由英国计算机科学家C.A.R. Hoare提出。它使用分治策略,选择一个基准元素,将数组分为两部分,一部分的所有元素都小于基准,另一部分的元素都大于基准,然后递归地对这两部分...
7. 堆排序:利用了二叉堆的数据结构,可以看作是完全二叉树的数组表示。首先构造一个大顶堆(或小顶堆),然后将堆顶元素与末尾元素交换,接着对剩余元素重新调整为堆,重复此过程,直到所有元素都被排序。 这七种...
Hoare发明,是目前最常用的排序算法之一。它采用分治策略,选取一个“基准”元素,将数组分为两部分:一部分的所有元素都小于基准,另一部分的所有元素都大于基准。然后对这两部分递归地进行快速排序。平均情况下,...
简单的堆排序算法:以定长数组为例,动态数组等可以以此类推
快速排序是最著名的内部排序算法之一,由分治策略实现。通过选择一个基准值并将数组分为两部分,使得一部分的所有元素小于另一部分。快速排序的平均时间复杂度为O(n log n),但在最坏情况下为O(n^2)。 7. **简单...
Hoare在1960年提出,是目前最常用的内部排序算法之一。快速排序的核心思想是分治法:选取一个基准元素,将数组划分为两部分,一部分的元素都小于基准,另一部分的元素都大于基准,然后对这两部分分别进行快速排序。...
堆排序,堆排序是一种基于比较的排序算法,它利用二叉堆的数据结构来排序元素。堆排序分为两个阶段:建立堆(heapify)和执行排序。
4. 堆排序:利用堆这种数据结构进行排序,分为建堆和调整堆两个过程。时间复杂度在所有情况下为O(n log n)。 5. 希尔排序:插入排序的优化版本,通过设置间隔序列来减少元素的移动次数。时间复杂度在最好情况下接近...
实现以下常用的内部排序算法并进行性能比较:"直接插入排序"," 折半插入排序"," 2—路插入排序"," 表插入排序"," 希尔排序"," 起泡排序"," 快速排序"," 简单选择排序"," 树形选择排序"," 堆排序"," 归并排序"," 链式...
Hoare在1960年提出,是目前应用最广泛的排序算法之一。它采用分治策略,通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行...
堆排序虽然在最坏情况下时间复杂度较高,但仍是原地排序算法,适用于内存受限的情况;计数排序则在特定条件下能提供线性的排序速度,但对数据类型和范围有所限制。在实际问题中,选择合适的排序算法需要根据数据特性...
在这个"排序算法演示小程序"中,我们可以看到六种经典的排序算法被实现和演示:交换排序、快速排序、插入排序、堆排序、选择排序以及希尔排序。这些算法在不同的场景下各有优势,理解它们的工作原理和性能特性对于...
堆排序是一种高效的比较排序算法,其主要思想是利用堆这种数据结构进行数据的排序。堆是一个近似完全二叉树的结构,同时满足堆的性质:即父节点的键值总是大于或等于(在最大堆中)或小于或等于(在最小堆中)其子...
堆排序是一种基于比较的排序算法,它通过构造一个大顶堆或小顶堆来实现排序。...尽管现代计算机中有更快的排序算法(如快速排序、归并排序等),但堆排序因其简单性和稳定性,仍然是许多程序员的首选工具之一。
堆排序是一种基于比较的排序算法,它通过构造一个近似完全二叉树的堆数据结构来实现排序。在计算机科学中,堆是一个可以被看作是一棵树形结构的数据集合,其中每个父节点的值都大于或等于其子节点的值(大顶堆)或...
此外,为了测试和验证这些排序算法的正确性,你可以编写一系列单元测试,覆盖不同情况下的输入,如已排序、逆序、随机序列等。这将确保代码的健壮性和准确性。 在实际项目中,选择合适的排序算法取决于具体的需求,...