您的位置:首页 > 其它

堆排序

2017-04-10 21:58 211 查看
小堆排序

堆排序是一种选择排序。

两个过程:1.初始建堆BuildHeap 2.移除根,重新建堆RebuildHeap

核心行为是:对于一个 除了根节点外,子树都是小根堆的数据进行根的调节。即AdjustHeap

AdjustHeap:从root往下都是满足小根堆,那么,需要对root数据进行调节。从root的child找,对比leftChild和rightChild,选两者中较小的和rootVal对比,

       决定是否把child的数据赋给root结点,然后继续从childIndex往下搜,找到一个结点放置rootVal。

1.初始建堆, 叶子结点是满足小根堆的,从最后一个非叶子结点开始进行AdjustHeap,上溯到Root,初始建堆完成

2.移除根节点后,把最后一个叶子放入rootIndex,进行AdjustHeap的过程。不停的移除root,直到最后没数据

以下为测试代码:其中数组的第一个索引0没有使用。。

#include<iostream>

using namespace std;

void HeapAdjust(int arr[], int begIdx, int endIdx);
void HeapBuild(int arr[], int begIdx, int endIdx);
void HeapRebuild(int arr[], int begIdx, int endIdx);
int const arrSize = 9;
void main()
{
int arrTest[arrSize] = { 4,53,36,30,91,47,12,24,85 };//第一个参数不参与对比,因为树根节点索引为1
HeapBuild(arrTest, 1, arrSize - 1);
HeapRebuild(arrTest, 1, arrSize - 1);
return;
}

#pragma region 小根堆排序
/*
*建堆,实际上是从叶子的父节点开始,进行从下往上的调堆过程
*/
void HeapBuild(int arr[], int begIdx, int endIdx)
{
for (int i = endIdx / 2; i >= begIdx; --i)
{
HeapAdjust(arr, i, endIdx);
}
}
/*初始堆后,移除root重建过程*/
void HeapRebuild(int arr[], int begIdx, int endIdx)
{
int rootVal = arr[begIdx];
arr[begIdx] = arr[endIdx];
arr[endIdx] = rootVal;

int offsetNum = 0;
for (int i = begIdx; i < endIdx - offsetNum; ++i, ++offsetNum)
{
int lastIdx = endIdx - offsetNum-1;
HeapAdjust(arr, begIdx, lastIdx);
//交换数据
int temp = arr[begIdx];
arr[begIdx] = arr[lastIdx];
arr[lastIdx] = temp;
}
}

/*调堆的过程,除了根外,其他结点都是有序的*/
void HeapAdjust(int arr[], int begIdx, int endIdx)
{
int rootVal = arr[begIdx];//无序的根结点
int tempIdx = begIdx;
//从子节点往下搜
for (int i = 2 * begIdx; i <= endIdx; i = 2 * i)
{
//对比左右子树,确保小的和父节点对比
if ((i + 1) <= endIdx&&arr[i] > arr[i + 1])
{
i = i + 1;
}
if (rootVal <= arr[i])
{
break;
}
else
{
arr[tempIdx] = arr[i];//数据上移动
tempIdx = i;//坑变了
}
}
arr[tempIdx] = rootVal;//最后把tempRootVal赋值给空余的坑下
}
#pragma endregion
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: