项目介绍
- 本项目通过分解各大厂的常见笔面试题,追本溯源至数据结构和算法的底层实现原理,知其然知其所以然;
- 建立知识结构体系,方便查找,欢迎更多志同道合的朋友加入项目AlgorithmPractice,(欢迎提issue和pull request)。
什么是堆排序
- 数组,按照树的结构来存储,即数组的第 i 位,其左孩子如果存在,那么存储在 2i+1 位上,其右孩子如果存在,那么存储在 2i+2 位上。
- 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆
两种解法
正文开始
1、建堆整堆法
- 代码实现:HeapSort,测试用例:HeapSortTest
- 设计思路:
- 首先从数组的n/2开始,往回遍历至0,
- 对于每个遍历到的元素,需要依次对其左右孩子进行对比,数值大的进行交换
- 发生交换的情况下,需要再依次进行递归比较
- 主要代码:
建堆和整堆
public void sortMethod(int[] heap) {
int temp;
if (!check(heap)) {
return ;
}
for (int i = (heap.length - 1) / 2; i >= 0 ; i--) {
heapify_big(heap, i, heap.length - 1);
}
for (int i = heap.length - 1; i > 0; i--) {
temp = heap[0];
heap[0] = heap[i];
heap[i] = temp;
heapify_big(heap, 0, i-1);
}
}
整堆的细节
public void heapify_big(int[] heap, int parent, int border){
int flag = parent * 2 + 1;
if(flag > border){
return ;
}
if(flag + 1 <= border){
flag = heap[flag] > heap[flag + 1] ? flag : flag + 1;
}
if(heap[flag] > heap[parent]){
int temp = heap[flag];
heap[flag] = heap[parent];
heap[parent] = temp;
heapify_big(heap, flag, border);
}
}
2、直接整堆法
public void sortMethod(int[] array) {
if (!check(array)) {
return;
}
int length = array.length - 1;
for (int i = 0; i < length; i++) {
heapify_big(array, length - i);
int temp = array[0];
array[0] = array[length - i];
array[length - i] = temp;
}
}
public void heapify_big(int[] array, int bound) {
int mid = (bound - 1) / 2;
int temp;
for (int i = mid; i >= 0; i--) {
int flag = 2 * i + 1;
if (flag + 1 <= bound) {
flag = array[flag] > array[flag + 1] ? flag : flag + 1;
}
if (flag <= bound && array[flag] > array[i]) {
temp = array[flag];
array[flag] = array[i];
array[i] = temp;
}
}
}
- 注意事项:
- 建堆整堆法,是先建堆,然后维护它,维护的时候,会有递归的操作
- 直接整堆法,是通过两层循环实现,不需要递归的。