我在学校学习Java中的排序算法,我的作业是堆排序。我读了很多资料,尽力理解,但似乎无法掌握概念。
我不要求你为我编写Java程序,如果您能尽可能简单地向我解释堆排序如何工作,那就太好了。
我在学校学习Java中的排序算法,我的作业是堆排序。我读了很多资料,尽力理解,但似乎无法掌握概念。
我不要求你为我编写Java程序,如果您能尽可能简单地向我解释堆排序如何工作,那就太好了。
简单来说,你需要取出堆中的第一个节点 - 因为第一个节点保证是最大值或最小值(根据排序顺序)。但难点在于首先要重新平衡/创建堆。
要理解堆排序过程,需要两个步骤 - 首先将其视为一棵树并理解它的结构,然后将该树转换为数组以便于使用。
第二部分是以广度优先的方式遍历树,从左到右将每个元素添加到数组中。例如以下树形结构:
73
7 12
2 4 9 10
1
给定数组{73,7,12,2,4,9,10,1}。
第一步需要两个步骤:
因此,要对数字列表进行堆化,您需要将每个数字添加到堆中,然后按顺序执行这两个步骤。
为了创建上面的堆,我首先加入10-它是唯一的节点,所以什么也不用做。 然后将12作为左侧子节点添加:
10
12
这满足了条件1,但不满足条件2,因此我将它们交换一下:
12
10
加7 - 无事可做
12
10 7
添加73
12
10 7
73
10 < 73 所以需要交换它们:
12
73 7
10
12 < 73 所以需要交换它们:
73
12 7
10
添加2-无操作
73
12 7
10 2
加4 - 无事可做
73
12 7
10 2 4
加上9
73
12 7
10 2 4 9
7 < 9 - 交换
73
12 9
10 2 4 7
加1 - 无需操作
73
12 9
10 2 4 7
1
我们有自己的堆:D
现在你只需要从顶部删除每个元素,每次将最后一个元素交换到树的顶部,然后重新平衡树:
取下73-放置1在它的位置
1
12 9
10 2 4 7
1 < 12 - 因此交换它们
12
1 9
10 2 4 7
1 < 10 - 因此交换它们
12
10 9
1 2 4 7
减去12,替换为7
7
10 9
1 2 4
将 7 和 10 交换位置
10
7 9
1 2 4
减去10,替换为4。
4
7 9
1 2
4 < 7 - swap
7
4 9
1 2
交换7和9的位置
9
4 7
1 2
减去9,替换为2
2
4 7
1
将2和4进行交换 - 2 < 4
4
2 7
1
将 4 和 7 交换位置
7
2 4
1
把7减去,替换为1
1
2 4
将1和4互换 - Swap them
4
2 1
进行第四次替换,使用一个元素代替
1
2
将 1 和 2 交换位置
2
1
采用第二种方法,替换为第一种方法
1
第一步
排序后的列表,完成。
这样就对数组进行了排序,因为由Delete-Max返回的元素是按降序排列的。一旦所有元素都被删除,数组就会被排序。
堆排序是高效的,因为堆上的Insert和Delete-Max操作都在O(log n)时间内运行,这意味着可以在O(n log n)时间内对堆进行n个插入和删除操作。可以使用更精确的分析来表明,实际上无论输入数组如何,它都需要Θ(n log n)时间。
通常情况下,堆排序采用两种主要优化。首先,堆通常是在数组内部原地构建的,通过将数组本身视为堆的压缩表示。如果您查看堆排序实现,通常会看到基于乘法和除法的数组索引的不寻常用法;这些访问之所以有效,是因为它们将数组视为一种压缩的数据结构。因此,该算法仅需要O(1)辅助存储空间。std::sort
函数实现中使用的算法,一旦您掌握了堆排序算法,就不难自己实现它。
希望这可以帮到您!
我记得我的算法分析教授告诉我们,堆排序算法的工作原理就像一堆碎石头:
想象一下你有一个装满碎石的袋子,你把它倒在地上:大石头很可能会滚到底部,而较小的石头(或沙子)则会留在顶部。
现在你取出堆的最顶端,并将其保存在堆的最小值处。然后再把剩下的堆放回袋子里,重复这个过程。 (或者你可以采用相反的方法,拿起你在地上看到的最大的石头,这个例子仍然是有效的)
这就是我知道的解释堆排序工作原理的简单方式。
堆排序是一种最简单的算法,时间复杂度为O(nlogn),空间复杂度为O(1)。
public class HeapSort {
public static void main(String[] args) {
Integer [] a={12,32,33,8,54,34,35,26,43,88,45};
HeapS(a,a.length-1);
System.out.println(Arrays.asList(a));
}
private static void HeapS(Integer[] a, int l) {
if(l<=0)
return;
for (int i = l/2-1; i >=0 ; i--) {
int index=a[2*i+1]>a[2*i+2]?2*i+1:2*i+2;
if(a[index]>a[i]){
int temp=a[index];
a[index]=a[i];
a[i]=temp;
}
}
int temp=a[l];
a[l]=a[0];
a[0]=temp;
HeapS(a,l-1);
}
}