堆排序

本文介绍了堆排序的基本概念,包括堆结构的特点及如何利用这些特点完成数据排序的过程。通过具体的筛运算步骤说明了如何构建并调整堆结构,最终实现从小到大的排序。

利用堆结构和二叉树的一些性质来完成数据的排序。


堆结构:
  完全二叉树
在这个树中每个结点对应于原 始数据的一个记录,并且每个结点应满足以 下条件:
• 如果 按照从小 到大的 顺序排序,要求非叶结点的数据要大于或等于其左 、 右子结点的数据。
• 如果按照从大到 小 的 顺序排序,要求非叶结点的数据要小 于或等于其左 、 右子结点的数据。
这里以 从小 到大的 顺序进行排序为例进行介绍。 从堆结构的定义可以 看出,对结点的左子结点和 右子结点的大小 没有要求, 只 规定父结点和子结点数据之间必 须满足的大小 关系 。这 样 ,如果要求按照从小 到大的 顺序输出数据时, 则 堆结构的根结点为要求的最大值。


堆排序过程:
 反复两个过程:构造堆结构和堆排序输出
 构造堆结构就是把原 始的 无序数据按前面堆结构的定义进行调 整。 首先 , 需要将原始的无序数据放置到一个完全二叉树的 各个结点中,这可以 按照前面介绍的方法来实现。
然 后 , 由 完全二叉树的 下层向 上层逐层进行父子结点的数据进行比较, 使父结点的数据大于子结点的数据。这里需要使用 筛运算进行结点数据的 调 整, 直到使所有结点最后满足堆结构的条件为止 。 筛运算主要针对非叶结点进行调 整。
例如,对于一个非叶结点 Ai,这里假定 鴻的 左 子树和 右 子树均 已 进行筛运算,也就是说其左子树和 右子树均 已构成堆结构。 下 面,对 鴻 进行 筛 运 算, 操作步骤如 下 :
( 1 ) 比较Ai的 左 子树和 右子树的最大值, 将 最大值 放 在 Aj中。
(2) 将Ai的数据与 Aj 的数据进行 比较 ,如果 Ai 大于等于 Aj , 表示以 Ai为根的子树已构成堆结构,便可以 终止筛运算。
(3) 如果 Ai小 于 Aj , 则将 Ai与 Aj互 换 位 置 。
(4) 经 过 第 (3 ) 步后 ,可 能 会破 坏 以Ai为根的 堆 , 因 为 此时 Ai 的值为 原 来的 Aj 。 下 面 以 Aj为根重复前面的 步骤, 直到 满足堆结构的定义,也就是父结点数据大于子结点。这 样 ,以 Aj为根的子树就被调 整为一个堆。在执行筛运算时,值较小 的数据将被逐层下移。


// HeapSort.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include<IOSTREAM>
#include<CSTDIO>
#include<CSTDLIB>
#include<CSTRING>
#include<CTIME>

using namespace std;

#define  SIZE 10


void HeapSort(int a[], int n)
{
	int i, j, h, k;
	int t;
	
	for (i = n / 2-1; i >= 0; i--)
	{
		while(2 * i + 1 < n)
		{
			j = 2 * i + 1;
			if ((j + 1) < n)
			{
				if (a[j] < a[j +1])
				{
					j++;
				}
			}
			if (a[i] < a[j])
			{
				t = a[i];
				a[i] = a[j];
				a[j] = t;
				i = j;
			}
			else
			{
				break;
			}
		}
	}
	cout<<"org array Heap: "<<endl;
	for (h = 0; h < n; h++)
	{
		cout<<a[h]<< " ";
	}
	cout<<endl;
	
	for (i = n - 1; i > 0; i--)
	{
		t = a[0];
		a[0] = a[i];
		a[i] = t;
		k = 0;
		while(2 * k + 1 < i)
		{
			j = 2 * k + 1;
			if ((j + 1) < i)
			{
				if(a[j] < a[j +1])
				{
					j++;
				}
			}
			if (a[k] < a[j])
			{
				t = a[k];
				a[k] = a[j];
				a[j] = t;
				k = j;
			}
			else
			{
				break;
			}
		}
		cout<<"step "<< n - i << " sort"<<endl;
		for (h = 0; h < n; h++)
		{
			cout<<a[h]<< " ";
		}
		cout<<endl;
	}
}




int main(int argc, char* argv[])
{
	int array[SIZE], i;
	
	srand(time(NULL));
	for (i = 0;i < SIZE; i++)
	{
		array[i] = rand() / 10000 + 100;
	}
	
	cout<<"before sort -------------"<<endl;
	for (i = 0; i < SIZE; i++)
	{
		cout<<array[i]<<" ";
	}
	cout<<endl;
	HeapSort(array, SIZE);
	
	cout<<"Sort: ------------------"<<endl;
	for (i = 0; i < SIZE; i++)
	{
		cout<<array[i]<<" ";
	}
	cout<<endl;
	getchar();
	return 0;
}





before sort -------------
101 100 100 102 100 100 102 102 101 100
org array Heap:
102 102 102 101 100 100 100 100 101 100
step 1 sort
102 101 102 101 100 100 100 100 100 102
step 2 sort
102 101 100 101 100 100 100 100 102 102
step 3 sort
101 101 100 100 100 100 100 102 102 102
step 4 sort
101 100 100 100 100 100 101 102 102 102
step 5 sort
100 100 100 100 100 101 101 102 102 102
step 6 sort
100 100 100 100 100 101 101 102 102 102
step 7 sort
100 100 100 100 100 101 101 102 102 102
step 8 sort
100 100 100 100 100 101 101 102 102 102
step 9 sort
100 100 100 100 100 101 101 102 102 102
Sort: ------------------
100 100 100 100 100 101 101 102 102 102


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值