堆排序的步骤如下:
首先建立堆,然后引入了循环不变式,就是初始情况下,整个数组都为堆,然后始终把堆的根,也就是第一个元素与堆的最后一个元素交换,这样每次交换后,从堆最后一个元素开始到结束是有序的,最后堆化前面无序区,直到堆只剩下一个元素!
这个不变式和选择排序等不变式一样,分成两部分,前面堆部分为无序区,后面为有序区!
堆排序与选择排序的区别在于:选择排序每次都比较得到最大的值,而堆排序也是每次得到最大值,但是通过堆的特点记录了上次部分比较结果,使得下次比较次数减少!
堆排序的核心在于堆化部分,开始是堆化整个数组,后面是依次堆化数组中的无序部分!
为整个数组建堆的过程是自底向上的,理解这一点很重要,因为堆的定义是递归定义的!所以建堆过程是从最后高度为二的节点开始的,也就是length/2.
在为每一个节点堆化的过程中,我们是从该节点和其左右子节点中,寻找出最大的那个,并且把最大值与该节点交换!当最大的节点为子节点的某一个时候,交换后还需要递归堆化该子节点!(在理解这一点时,我花了瞒长时间,因为我忽略了其左右子节点为堆这个事实!)
上面部分是原理部分!
编写具体代码上,以下卡了一段时间
在堆化的过程中,分清楚数组的值是从0开始的,而堆元素的根是从1这个序列开始,把该节点和其左右子节点的计算和在数组中的位置表示出来,如果混用的化,则得不到理想的结果!
每次在无序区堆化的时候,特别注意的是,无序区动态减少,所以堆化的堆大小每次循环时候都减小的事实,不可以忽略!
以下是实现代码:
public class HeapSort {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
buildHeap(arr);
System.out.println("this is build heap result:");
for(int i:arr){
System.out.print(i);
}
heapSort(arr);
System.out.println("");
System.out.println("this is sorted by heapSort result:");
for(int i:arr){
System.out.print(i);
}
}
public static void heapfy(int[] arr,int i,int heapSize){
int largest;
int l = 2*i-1;
int r = 2*i;
if(l<heapSize&&arr[l]>arr[i-1])
largest = l;
else
largest = i-1;
if(r<heapSize&&arr[r]>arr[largest])
largest = r;
if(largest!= i-1){
swap(arr,i-1,largest);
heapfy(arr,largest+1,heapSize);
}
}
public static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void buildHeap(int[] arr){
for(int i=arr.length/2;i>0;i--){
heapfy(arr,i,arr.length);
}
}
public static void heapSort(int[] arr){
buildHeap(arr);
for(int i=0;i<arr.length;i++){
swap(arr,0,arr.length-1-i);
heapfy(arr,1,arr.length-i-1);
}
}
}
分享到:
相关推荐
最终实现了将2048点堆排序的时间控制在2ms以内,这一结果与原ARM上位机处理速度相当,满足了设计的需求。 堆排序算法是一种利用堆积树数据结构的排序方法,可快速定位数组中指定索引的元素。堆排序分为建堆和排序两...
常见的排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、计数排序、桶排序、基数排序等。 2. **冒泡排序** 冒泡排序是最简单的排序算法之一,通过重复遍历数组,比较相邻元素并交换位置来...
实验要求学生至少实现三种经典的排序算法:冒泡排序、快速排序和堆排序。 1. **冒泡排序**是一种简单的交换排序方法,通过反复遍历待排序序列,每次比较相邻两个元素并根据需要交换位置,使得较大的元素逐渐“浮”...
文件“排序算法的比较_C++.doc”虽然名字中提到了C++,但其内容可能涵盖了C语言的排序算法,比如冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序等。这些经典的排序算法各有优缺点,理解它们的工作原理...
2. 冒泡排序、直接插入排序、简单选择排序、希尔排序、快速排序、堆排序、归并排序等内部排序算法的实现 3. 排序算法的性能比较,包括键比较次数和键移动次数 4. 随机数生成器的使用 5. C语言的应用 6. 程序算法的...
8. 堆排序:是一种高效的排序算法,通过构建最大或最小堆,并将堆顶元素取出来实现排序。 9. 基数排序:是一种非比较排序算法,通过将数组分为多个桶,并对各桶进行排序来实现排序。 10. 外部排序:是一种排序算法...
常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序等。快速排序以其平均时间复杂度为O(n log n)而备受青睐,但最坏情况下会退化到O(n^2),因此理解它的优化策略如三向切分非常关键。归并...
给出的冒泡排序和选择排序函数展示了如何在C语言中实现基本排序算法。 字符串在C语言中是字符数组的特殊形式,通常以空字符'\0'结束。处理字符串时要注意字符串长度的计算和字符串复制的正确方法。 指针是C语言最...
第二种算法是堆排序,它通过使用堆数据结构来实现排序。该算法的难点在于如何调整堆,使得父节点的值大于或等于子节点的值。解决方法是使用 sift 函数来调整堆,通过比较父节点和子节点的值来确定它们的顺序。 第三...
9. **排序**:数据结构课件中还会涵盖各种排序算法,如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等,这些算法对于理解和优化数据处理至关重要。 10. **查找**:查找算法包括顺序查找、二分查找、...
36. 冒泡和选择排序实现 180 37. 函数指针数组与返回数组指针的函数 186 38. 右左法则- 复杂指针解析 189 39. 回车和换行的区别 192 40. 堆和堆栈的区别 194 41. 堆和堆栈的区别 198 42. 如何写出专业的C头文件 202 ...
此外,快速排序的递归和非递归实现、锦标赛排序的优化、堆排序的完全二叉树结构、归并排序的空间效率优化和外排序的I/O优化等都是需要深入理解的内容。 教材中的习题解析通常会帮助巩固这些知识点,例如题目9-1解释...
4. 堆与优先队列的表示,包括基本操作和实际应用,如堆排序和优先级队列的构建。 5. 图论的基本定义和算法,如最小生成树、单源最短路径和全局最短路径问题。 C++编程方面,要求学生熟悉类定义、递归、内存管理...
C语言是一种底层编程语言,广泛应用于系统开发、嵌入式编程等领域。对于初学者来说,理解和掌握...同时,了解C语言的内存管理机制,如堆栈和堆的使用,以及预防和处理内存泄漏等问题,也是成为C语言高手的必经之路。
5. **排序与查找**:排序算法如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等,它们对数据进行有序排列;查找算法如顺序查找、二分查找、哈希查找等,帮助我们快速定位数据。 6. **特殊数据结构**:...
1. **实验目的**:实验者需要通过编程实现不同的排序算法,包括插入排序、冒泡排序(改进型)、快速排序、简单选择排序和堆排序(小根堆)。目标是理解这些算法的核心思想和执行流程,并掌握它们在不同数据状态...
重点难点包括理解每种排序算法的基本思想,如快速排序的分治策略、堆排序的堆结构构建以及外部排序中的多路归并等。此外,还要能够分析排序算法的性能,判断其是否稳定,并在实际问题中灵活应用。 学习排序算法不仅...
在“三种常见排序算法分析”中,可能包含了冒泡排序、选择排序和插入排序的原理和实现。理解这些基础算法有助于提高编程能力。 掌握以上知识点,不仅能帮助考生顺利通过二级考试,也能为他们日后的编程实践打下坚实...
知识目标包括理解各种排序算法的基本原理、步骤,以及排序算法的规则,如插入类排序(直接插入排序、希尔排序)、交换类排序(冒泡排序、快速排序)、选择类排序(直接选择排序、堆排序)和归并类排序的细节。...
冒泡和选择排序实现 这部分提供了冒泡排序和选择排序的具体实现。 ### 37. 函数指针数组与返回数组指针的函数 这部分介绍了函数指针和数组指针的高级用法。 ### 38. 右左法则- 复杂指针解析 这部分探讨了复杂的...