1. 思路
数组存储数,左结点坐标=父结点坐标*2+1,右节点左坐标=左结点+1,父结点坐标=(子节点坐标-1)/2
2. 过程
先建堆,再输出
建堆1:从上往下建堆,插入结点,比如建立大顶堆,插入时比较当前结点和父结点大小,子节点比父结点大就交换位置,当前结点移动到父结点位置。
建堆2:直接从下往上建堆。判断是不是最后一个结点,如果不是,就比较左右父结点大小,最大的放上面,当前结点标记为最大的结点。
3. 代码
public int[] heapSort(int[] arr) {
if (arr == null || arr.length < 2) {
return arr;
}
// O(NlogN) 在尾部加入元素
// for (int i = 0; i < arr.length; i++) {//O(N)
// heapInsert(arr, i);//logN
// }
//O(N) Floyd建堆法 从后往前
for (int i =arr.length-1; i >=0 ; i--) {
heapify(arr, i, arr.length);
}
int heapSize = arr.length;
heapSize--;
//交换根结点和最后一个结点
swap(arr, 0, arr.length - 1);
while (heapSize > 0) {
heapify(arr, 0, heapSize);
heapSize--;
swap(arr, 0, heapSize);
}
return arr;
}
/**
* 在数组指定位置插入元素
*
* @param arr
* @param index
*/
public void heapInsert(int[] arr, int index) {
//大顶堆,插入的元素和父元素进行比较
while (arr[index] > arr[(index - 1) / 2]) {
//交换当前结点和父结点的位置
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
public void heapify(int[] arr, int index, int heapSize) {
//左子节点
int left = 2 * index + 1;
//如果下放还有结点
while (left < heapSize) {
//左右子节点找到最大的位置
int largest = (left + 1) < heapSize && arr[left+1] > arr[left] ? left+1 : left;
//当前结点和左右子节点中最大的位置
largest = arr[index] > arr[largest] ? index : largest;
//当前结点即为最大值,则不用变
if (index == largest) {
break;
}
//否则
swap(arr, index, largest);
//跳转到最大结点
index = largest;
left = 2 * index + 1;
}
}