您的位置:首页 > 理论基础 > 数据结构算法

数据结构一一堆排序

2018-01-29 11:51 197 查看
堆排序:一种树形选择排序,是对直接选择排序的有效改进。



综上描述,它的实现需要解决两个问题:

1、如何由一个无序序列构建成一个堆?

2、如何在输出堆顶元素后,调整剩余元素成为一个新的堆?

无序序列构建成一个堆的代码如下:

/**
* 初始堆进行调整
* 将L->iElem[0..length-1]建成堆
* 调整完之后第一个元素是序列的最小的元素
*/
void BuildingHeap(SqList* L)
{
//最后一个有孩子的节点的位置 i= (length -1) / 2
for (int i = (L->iLength -1) / 2 ; i >= 0; --i)
HeapAdjust(L,i,L->iLength);
}
void HeapAdjust(SqList* L,int s, int length)
{
int tmp  = L->iElem[s];
int child = 2*s+1;						//左孩子结点的位置。(i+1 为当前调整结点的右孩子结点的位置)
while (child < length)
{
if(child+1 <length && L->iElem[child]<L->iElem[child+1]) // 如果右孩子大于左孩子(找到比当前待调整结点大的孩子结点)
{
++child ;
}
if(L->iElem[s]<L->iElem[child]) // 如果较大的子结点大于父结点
{
L->iElem[s] = L->iElem[child]; // 那么把较大的子结点往上移动,替换它的父结点
s = child;       // 重新设置s ,即待调整的下一个结点的位置
child = 2*s+1;
}
else		// 如果当前待调整结点大于它的左右孩子,则不需要调整,直接退出
{
break;
}
L->iElem[s] = tmp;   // 当前待调整的结点放到比其大的孩子结点位置上
}
PrintList(*L);
}
将堆顶元素输出,即与最后一个元素进行交换,然后调整剩余元素成为一个新的堆
//从最后一个元素开始对序列进行调整
for (int i = L->iLength - 1; i > 0; --i)
{
//交换堆顶元素L->iElem[0]和堆中最后一个元素
Swap(L,0,i);
//每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
HeapAdjust(L,0,i);
}
整体代码实现如下:
#include <iostream>
#include <time.h>
using namespace std;

#define MAX_SIZE 9
typedef struct
{
int iElem[MAX_SIZE];
int iLength;
}SqList;

void PrintList(SqList L)
{
for (int i=0;i<L.iLength;i++)
{
cout<<L.iElem[i]<<" ";
}
cout<<endl;
}

void CreateList(SqList* L)
{
int i = 0;
L->iLength = 0;
srand((unsigned)time(NULL));
int iData[MAX_SIZE]={50,10,90,30,70,40,80,60,20};
for (i=0; i<MAX_SIZE; i++)
{
//L->iElem[i] = rand()%100;
L->iElem[i] = iData[i];
L->iLength++;
}
PrintList(*L);
}

void Swap(SqList* L,int a,int b)
{
int temp = L->iElem[a];
L->iElem[a] = L->iElem[b];
L->iElem[b] = temp;
}

void HeapAdjust(SqList* L,int s, int length)
{
int tmp = L->iElem[s];
int child = 2*s+1; //左孩子结点的位置。(i+1 为当前调整结点的右孩子结点的位置)
while (child < length)
{
if(child+1 <length && L->iElem[child]<L->iElem[child+1]) // 如果右孩子大于左孩子(找到比当前待调整结点大的孩子结点)
{
++child ;
}
if(L->iElem[s]<L->iElem[child]) // 如果较大的子结点大于父结点
{
L->iElem[s] = L->iElem[child]; // 那么把较大的子结点往上移动,替换它的父结点
s = child; // 重新设置s ,即待调整的下一个结点的位置
child = 2*s+1;
}
else // 如果当前待调整结点大于它的左右孩子,则不需要调整,直接退出
{
break;
}
L->iElem[s] = tmp; // 当前待调整的结点放到比其大的孩子结点位置上
}
PrintList(*L);
}
/**
* 初始堆进行调整
* 将L->iElem[0..length-1]建成堆
* 调整完之后第一个元素是序列的最小的元素
*/
void BuildingHeap(SqList* L)
{
//最后一个有孩子的节点的位置 i= (length -1) / 2
for (int i = (L->iLength -1) / 2 ; i >= 0; --i)
HeapAdjust(L,i,L->iLength);
}
/**
* 堆排序算法
*/
void HeapSort(SqList* L)
{
//初始堆
BuildingHeap(L);
//从最后一个元素开始对序列进行调整
for (int i = L->iLength - 1; i > 0; --i)
{
//交换堆顶元素L->iElem[0]和堆中最后一个元素
Swap(L,0,i);
//每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
HeapAdjust(L,0,i);
}
}

int main()
{
SqList L;
CreateList(&L);
HeapSort(&L);
return 0;
}运行结果:

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