堆排序(Heapsort)是利用堆这种数据结构所设计的一种排序算法, 它是选择排序的一种. 可以利用数组的特点快速定位索引的元素.
(选择排序工作原理 - 第一次从待排序的数据元素中选出最小(或最大)的一个元素, 存放在序列的起始位置, 然后再从剩余的未排序元素中寻求到最小(大)元素, 然后放到已排序的尾部. 以此类推, 直到全部待排序的数据元素的个数为零)
其排序核心实现如下:
第一步:
第二步:
先变为最大堆先, 再执行第一步.
重复上面的两个步骤
参考:
#include
#include
#include
typedef struct _Heap
{
int* arr; /* 存储堆元素的数组 */
int size; /* 当前已存储的元素个数 */
int capacity; /* 当前存储的容量 */
}Heap;
bool initHeap(Heap& heap, int* orginal, int size);
void buildHeap(Heap& heap);
void adjustDown(Heap& heap, int index);
void heapSort(Heap& heap);
bool popMax(Heap& heap, int& value);
/* 初始化堆 */
bool initHeap(Heap& heap, int* orginal, int size)
{
heap.arr = orginal;
if (!heap.arr) return false;
heap.capacity = size;
heap.size = size;
/* 如果存在原始数据则构建堆 */
if (size > 0)
{
/* 方式一: 直接调整所有元素(建堆) */
buildHeap(heap);
}
return true;
}
/* 从最后一个父节点(size/2-1的位置)逐个往前调整所有父节点(直到根结点),
** 确保每个父节点都是一个最大堆, 最后整体形成一个最大堆
*/
void buildHeap(Heap& heap)
{
int i;
for (i = heap.size / 2 - 1; i >= 0; i--)
{
adjustDown(heap, i);
}
}
/* 将当前的节点和子节点调整成最大堆 */
void adjustDown(Heap& heap, int index)
{
int cur = heap.arr[index]; /* 当前待调整的节点 */
int parent, child;
/* 判断是否存在大于当前节点子节点, 如果不存在, 则堆本身是平衡的, 不需要调整;
如果存在, 则将最大的子节点与之交换, 交换后, 如果这个子节点还有子节点, 则要继续
按照同样的步骤对这个子节点进行调整 */
for (parent = index; (parent * 2 + 1) < heap.size; parent = child)
{
child = parent * 2 + 1;
/* 取两个字节点中最大的节点 */
if (((child + 1) < heap.size) && ((heap.arr[child]) < heap.arr[child + 1]))
{
child++;
}
/* 判断最大的节点是否大于当前的父节点 */
if (cur >= heap.arr[child]) /* 不大于, 则不需要调整, 跳出循环 */
{
break;
}
else /* 大于当前的父节点, 进行交换, 然后从子节点位置继续向下调整 */
{
heap.arr[parent] = heap.arr[child];
heap.arr[child] = cur;
}
}
}
/* 实现堆排序 */
void heapSort(Heap& heap)
{
if (heap.size < 1) return;
while (heap.size > 0)
{
int tmp = heap.arr[0];
heap.arr[0] = heap.arr[heap.size - 1];
heap.arr[heap.size - 1] = tmp;
heap.size--;
adjustDown(heap, 0); /* 向下执行堆调整 */
}
}
/* 删除最大的节点, 并获得节点的值 */
bool popMax(Heap& heap, int& value)
{
if (heap.size < 1) return false;
value = heap.arr[0];
heap.arr[0] = heap.arr[--heap.size];
adjustDown(heap, 0); /* 向下执行堆调整 */
return true;
}
int main()
{
Heap hp;
int origVals[] = { 1,2,3,87,93,82,92,86,95 };
int i = 0;
if (!initHeap(hp, origVals, sizeof(origVals) / sizeof(origVals[0])))
{
fprintf(stderr, "初始化堆失败!\n");
exit(-1);
}
for (i = 0; i < hp.size; i++)
{
printf("the %dth elemennt: %d\n", i, hp.arr[i]);
}
/* 执行堆排序 */
heapSort(hp);
printf("执行堆排序后的结果: \n");
for (i = 0; i < sizeof(origVals) / sizeof(origVals[0]); i++)
{
printf(" %d", origVals[i]);
}
system("pause");
return 0;
}
学到的知识要, 多复习, 多总结, 多敲. 需要时间的积累, 才能引起质的改变. 自己写不出来的永远是别人的.
分享一下我的技巧: 代数法把具体的数字带进去, 看看能能能找到规律(掌握思想).
还有就是画图, 也很重要. 用笔画出来, 把数代进去, 方法虽然笨, 但真的很实用, 好记忆不如烂笔头!!! 还有多用debug(调试工具)
我是小白, C/C++功力…, 你懂得, 写的文章可能不是很好. 如果存在问题, 欢迎大神给予评判指正.
错了不可怕, 可怕的是找不出bug, 谁没错过!!!
最近学操作系统我认为, 学什么都要成本(时间), 即使它是免费的, 我个人认为要挑来学, 挑重点来学, 而不是从头到尾, 除非考试考研.
这个知识点我没有完全掌握, 就是会了也要复习, 革命尚未成功, 同志还需努力!!! , 我会回来反复复习的
今日是: 2020年5月18日, (由于疫情的原因)现在没有返校. 写博客,也可自己加强记忆,就当写写日记吧!!!
希望给个赞: 反正你又不亏, 顺便而已