您的位置:首页 > 编程语言

堆排序完整代码带详解(续)

2009-10-06 16:52 246 查看
续上面,

上面的一个初始化构建堆和替换之后的构建堆是分开写的。

可以仔细看一下,初始化是从i=n/2..n开始到i=1..n开始构建的

 

而替换后是从i=1..n-1 ,i=1..n-2..构建的

只是构建的开始位置和结束位置不一样而已

 

所以完全可以合成一个函数,只是在构建堆的时候需要多写上一个从i=n/2到i=1的一个循环完成各个字数的构建。

 

完成代码如下:欢迎拍砖!

 

#include <stdlib.h>
#include <stdio.h>

#define MAX_SIZE 20
typedef int ElemType;

// 定义排序表
typedef struct HeapList
{
ElemType *keys;
int length;
}HeapList;

// 初始化排序表
void InitHeapList(HeapList &L)
{
L.keys = (ElemType*)malloc(MAX_SIZE * sizeof(ElemType));
L.length = 6;
int data[] = {38, 11, 9, 27, 96, 83};
for(int i = 0; i < 6; ++i)
L.keys[i + 1] = data[i];
}

// 打印排序表
void PrintHeapList(HeapList &L)
{
for(int i = 1; i <= L.length; ++i)
printf("%5d", L.keys[i]);
printf("/n");
}

//初始化大堆
void CreateBigHeap(HeapList &L)
{
int middle = L.length/2;
for(int i = middle; i > 0; i--)
{
if(((2*i + 1) > L.length) && (2*i <= L.length))
{
// 当没有右字树的时候只判断根节点和左字树的大小进行调换
if(L.keys[i] < L.keys[2*i])
{
L.keys[0] = L.keys[i];
L.keys[i] = L.keys[2*i];
L.keys[2*i] = L.keys[0];
}
}
if((2*i + 1) <= L.length)
{
// 左右子数都有
// 先比较左右字树哪个最大
int max = 2 * i;
if(L.keys[2*i] < L.keys[2*i + 1])max++;
if(L.keys[i] < L.keys[max])
{
L.keys[0] = L.keys[i];
L.keys[i] = L.keys[max];
L.keys[max] = L.keys[0];
}
}
}
}

// 初始化大堆之后,每一次的对前N-1个进行再次大堆
void heapfy(HeapList &L, int end)
{
//此时出去root节点,其余的还是都符合大堆的,可以从头结点和他的子节点对比较,一直比到没有没有孩子结点或者满足大堆的时候停止
for(int i = 1; 2*i <= end; i *=2)
{
if(2*i + 1 <= end)
{
// 还是三者对比,然后把i更新到替换到得为之
int max = 2*i;
if(L.keys[2*i] < L.keys[2*i + 1])max++;
// 右字树最大,那么把该字树根节点和他对换吧
L.keys[0] = L.keys[i];
L.keys[i] = L.keys[max];
L.keys[max] = L.keys[0];
// 切记,更新i的位置
i = max;
// 接下来跳出if,进入for的下一个循环,该此时继续把i的自树进行如上操作
}
if(2*i + 1 > end && 2*i <= end)
{
// 只有左子树啦
if(L.keys[i] < L.keys[2*i])
{
L.keys[0] = L.keys[i];
L.keys[i] = L.keys[2*i];
L.keys[2*i] = L.keys[0];
}
}
}
}

//  堆排序
void HeapSort(HeapList &L)
{
// 初始化一次大堆
CreateBigHeap(L);
// 把第一个和最后一个调换一下
L.keys[0] = L.keys[1];
L.keys[1] = L.keys[L.length];
L.keys[L.length] = L.keys[0];
for(int i = L.length - 1; i > 0; --i)
{
heapfy(L, i);
L.keys[0] = L.keys[1];
L.keys[1] = L.keys[i];
L.keys[i] = L.keys[0];
}
}

// 初始化大堆之后,每一次的对前N-1个进行再次大堆
void heapSortEvery(HeapList &L, int start, int end)
{
//此时出去root节点,其余的还是都符合大堆的,可以从头结点和他的子节点对比较,一直比到没有没有孩子结点或者满足大堆的时候停止
for(int i = start; 2*i <= end; i *=2)
{
if(2*i + 1 <= end)
{
// 还是三者对比,然后把i更新到替换到得为之
int max = 2*i;
if(L.keys[2*i] < L.keys[2*i + 1])max++;
// 右字树最大,那么把该字树根节点和他对换吧
L.keys[0] = L.keys[i];
L.keys[i] = L.keys[max];
L.keys[max] = L.keys[0];
// 切记,更新i的位置
i = max;
// 接下来跳出if,进入for的下一个循环,该此时继续把i的自树进行如上操作
}
if(2*i + 1 > end && 2*i <= end)
{
// 只有左子树啦
if(L.keys[i] < L.keys[2*i])
{
L.keys[0] = L.keys[i];
L.keys[i] = L.keys[2*i];
L.keys[2*i] = L.keys[0];
}
}
}
}

void HeapSort_(HeapList &L)
{
// 先创建堆
for(int i = L.length/2; i > 0; --i)
heapSortEvery(L, i, L.length);
L.keys[0] = L.keys[1];
L.keys[1] = L.keys[L.length];
L.keys[L.length] = L.keys[0];
for(int j = L.length - 1; j > 0; --j)
{
heapSortEvery(L, 1, j);
L.keys[0] = L.keys[1];
L.keys[1] = L.keys[j];
L.keys[j] = L.keys[0];
}

}

void main()
{
HeapList L;
InitHeapList(L);
PrintHeapList(L);
HeapSort_(L);
PrintHeapList(L);
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  struct