开搞
实际上是对完全二叉树的操作,先生成大根堆(该节点的子节点均小于该节点),
再逐步将头节点与尾节点交换,交换后堆化二叉树,又变成大根堆,重复操作,直到heapSize = 0
实现大根堆
用户每次输入一个数,经过与头节点比较做交换处理
//大根堆
void heapInsert(int a[], int Index) {
while (a[Index] > a[(Index - 1) / 2]) {
swap(a[Index], a[(Index - 1) / 2]);
Index = (Index - 1) / 2;
}
}
实现堆化
//前提是这颗二叉树已经是大根堆
//当我们改变某个以Index为下标节点的值后,heapify使下标以Index为头节点的完全二叉树 重新 堆化
void heapify(int a[], int Index, int heapSize) {
int left = (Index * 2) + 1;//左节点下标
while (left < heapSize) {
int right = ((Index * 2) + 2);//右节点
int biggest = (right < heapSize) && (a[right] > a[left]) ? right : left;//判断右节点是否存在,存在则比左右大小,返回大值下标
biggest = a[Index] > a[biggest] ? Index : biggest;//把左右孩子中较大值的下标和父节点比较,返回较大者的下标
if (a[Index] == a[biggest])break;//如果较大值的下标就是头节点,说明已经形成大根堆,跳出循环
swap(a[Index], a[biggest]);
Index = biggest;
left = (Index * 2) + 1;
}
}
实现堆排序
逐步将头节点与尾节点交换,交换后堆化二叉树,又变成大根堆,重复操作,直到heapSize = 0
这样[heapSize,a.length]就是有序的
//堆排序
//大根堆
void heapInsert(int a[], int Index) {
while (a[Index] > a[(Index - 1) / 2]) {
swap(a[Index], a[(Index - 1) / 2]);
Index = (Index - 1) / 2;
}
}
//前提是这颗二叉树已经是大根堆
//当我们改变某个以Index为下标节点的值后,heapify使下标以Index为头节点的完全二叉树 重新 堆化
void heapify(int a[], int Index, int heapSize) {
int left = (Index * 2) + 1;//左节点下标
while (left < heapSize) {
int right = ((Index * 2) + 2);//右节点
int biggest = (right < heapSize) && (a[right] > a[left]) ? right : left;//判断右节点是否存在,存在则比左右大小,返回大值下标
biggest = a[Index] > a[biggest] ? Index : biggest;//把左右孩子中较大值的下标和父节点比较,返回较大者的下标
if (a[Index] == a[biggest])break;//如果较大值的下标就是头节点,说明已经形成大根堆,跳出循环
swap(a[Index], a[biggest]);
Index = biggest;
left = (Index * 2) + 1;
}
}
//堆排序
//将大根堆的头节点交换到堆尾部,--heapSize;当heapSize==0时数组有序
void heapSort(int a[], int heapSize) {
//形成大根堆
for (int i = 0; i < heapSize; i++) heapInsert(a, i);
while (heapSize) {
//交换头尾节点
swap(a[0], a[--heapSize]);
//堆化
heapify(a, 0, heapSize);
}
}
时间复杂度O(Nlogn),空间复杂度O(1);
To see an oasis of place