伪代码
调整堆{数组首地址,数组长度,当前要调整节点下标}
保存当前节点到temp
建立用来寻找最小值的下标idx,初始化为左孩子
WHILE idx 没到数组尾:
将当前值、左孩子、右孩子三者之中的最小值的下标给idx
IF idx 没有变化:
BREAK
ELSE 用idx的值覆盖掉当前节点
把temp放到idx处
注意到调整的前提是整体是堆结构,只有一个节点需要调整。
堆排序:数组arr,长度len
从第一个非叶子节点,向前逐个调整,自底向上
idx=len-1
WHILE idx 不到开头
将首元素和末尾元素交换
调整{0……idx}位置的首元素
过程演示
代码实现
#pragma once
#include<iostream>
#include<cstdio>
using namespace std;
typedef int DataType;
const int MAX_SIZE = 9000;
struct RecordNode
{
DataType val;
RecordNode() {}
RecordNode(const DataType& data) :val(data) {}
void setVal(DataType item) {
val = item;
}
void show() {
cout << val << " ";
}
};
class SortObject
{
public:
int n;//记录个数
RecordNode* record;
SortObject(const int len, DataType* arr) :n(len) {
record =(RecordNode*)malloc(len * sizeof(RecordNode));
for (int i = 0; i < len; ++i)
{
record[i].setVal(arr[i]);
}
}
~SortObject() {}
void visit() {
for (int i = 0; i < n; ++i)
{
record[i].show();
}
cout << endl;
}
};
int getMin_i(SortObject * pvector, const int size,const int now_i, const int temp) {
//size是动态的有效范围
int ans_i = now_i;
DataType lval = INT_MAX, rval = INT_MAX;
int lchild= 2 * now_i + 1;
int rchild = lchild + 1;
if (lchild < size) {//下标合法
lval = pvector->record[lchild].val;
if(rchild<size) rval=pvector->record[rchild].val;
if (temp > lval) {
if (lval > rval) ans_i = rchild;
else ans_i = lchild;
}
else {
if (temp > rval) ans_i = rchild;
}
}
return ans_i;
}
void sift(SortObject * pvector, int size, int now_i)
{
RecordNode * data = pvector->record;
RecordNode temp = data[now_i];
while (true)
{
int down_i=getMin_i(pvector,size, now_i,temp.val);
if (now_i < down_i)//下沉,下标变大
{
data[now_i] = data[down_i]; /* 下面覆盖父亲*/
now_i= down_i;
}
else break;
}
data[now_i] = temp; /* 把元素放入正确位置 */
}
/*简化版
void sift(SortObject * pvector, int size, int now_i)
{
RecordNode * data = pvector->record;
RecordNode temp = data[now_i];
int child_i = 2 * now_i + 1;//leftchild is 2*i+1
while (child_i < size)
{
if ((child_i < size - 1) && (data[child_i].val > data[child_i + 1].val))
child_i++;//right child
if (temp.val > data[child_i].val)
{
data[now_i] = data[child_i];
now_i = child_i;
child_i = 2 * now_i + 1;
}
else break;
}
data[now_i] = temp;
}
*/
void heapSort(SortObject * pvector) /* 对记录R0到Rn-1进行堆排序 */
{
int i, n;
RecordNode temp;
n = pvector->n;
RecordNode * data = pvector->record;
for (i = n / 2 - 1; i >= 0; i--)
sift(pvector, n, i); /* 建立初始堆 */
for (i = n - 1; i > 0; i--)/* 进行n-1趟堆排序 */
{ /* 当前堆顶记录和最后一个记录互换 */
temp = data[0];
data[0] = data[i];
data[i] = temp;
sift(pvector, i, 0); /* 从R0到Ri-1重建堆,即调整 */
}
}
void test() {
int len = 8;
int arr[8] = { 49,38,65,97,76,13,27,50 };
SortObject obj(len, arr);
obj.visit();
SortObject* ptr = &obj;
heapSort(ptr);
obj.visit();
}