堆排序
1.堆
1.概念:本质上就是存储一棵完全二叉树的数组。
2.性质:
大堆:根节点>左孩子&&根节点>右孩子;
小堆:根节点<左孩子&&根节点<右孩子。
2.堆排序的实现
1.思路:
(1)对待排数组进行建堆操作
(2)每次取出首元素--最值放入另一个临时数组中来存放
(3)将临时数组中的值拷贝到原数组中去
过程:
2.实现:
降序--大堆
升序--小堆
#include <stdio.h>
#include <stdlib.h>
typedef struct Heap {
int* arr;
int size;
int capacity;
}Heap;
//1.堆的向下调整:只有pos下标处的元素有问题,其他位置均没有问题
//以建大堆为例 : 根节点 > 左孩子 && 根节点 > 右孩子
void adjustDown(Heap* ph, int pos) {
int left = pos * 2 + 1;
int right = pos * 2 + 2;
while (1) {
//判断是否是叶子结点了
if (pos >= ph->size -1 || left > ph->size - 1) {
break;
}
int max = left; //记录左右孩子中较大的下标
//判断有无右孩子
if (right <= ph->size - 1 && ph->arr[right] > ph->arr[left]) {
max = right;
}
if (ph->arr[pos] > ph->arr[max]) {
break;
}
//开始交换
int temp = ph->arr[max];
ph->arr[max] = ph->arr[pos];
ph->arr[pos] = temp;
pos = max;
left = pos * 2 + 1;
right = pos * 2 + 2;
}
}
void heapCreate(Heap* ph) {
for (int i = (ph->size - 2) / 2; i >= 0; --i) {
adjustDown(ph, i);
}
}
void heapSort(Heap* ph) {
heapCreate(ph);
int* newarr = (int*)malloc(sizeof(int)*ph->capacity);
for (int i = 0; i < ph->capacity; ++i) {
newarr[i] = ph->arr[0];
ph->arr[0] = ph->arr[ph->size];
--ph->size;
adjustDown(ph, 0);
}
ph->size = ph->capacity;
free(ph->arr);
ph->arr = NULL;
ph->arr = newarr;
}
int main() {
Heap ph;
int capacity = 10;
ph.arr = (int*)malloc(sizeof(int)*capacity);
ph.capacity = ph.size = capacity;
for (int i = 0; i < ph.size; ++i) {
ph.arr[i] = i;
}
printf("\n");
for (int i = 0; i < ph.size; ++i) {
printf("%d ", ph.arr[i]);
}
printf("\n");
heapCreate(&ph);
for (int i = 0; i < ph.size; ++i) {
printf("%d ", ph.arr[i]);
}
heapSort(&ph);
printf("\n排序后:");
for (int i = 0; i < ph.size; ++i) {
printf("%d ", ph.arr[i]);
}
system("pause");
return 0;
}