您的位置:首页 > 其它

排序算法——堆排序

2015-07-21 13:33 190 查看
堆排序快速排序归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。


二叉堆的定义

二叉堆是完全二叉树或者是近似完全二叉树。

二叉堆满足二个特性:

1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。下图展示一个最小堆:



由于其它几种堆(二项式堆,斐波纳契堆等)用的较少,一般将二叉堆就简称为堆。


堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。




堆的操作——插入删除

下面先给出《数据结构C++语言描述》中最小堆的建立插入删除的图解,再给出本人的实现代码,最好是先看明白图后再去看代码。




堆的插入

每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中——这就类似于直接插入排序中将一个数据并入到有序区间中,对照《白话经典算法系列之二
直接插入排序的三种实现》不难写出插入一个新数据时堆的调整代码。

// tt.cpp : 定义控制台应用程序的入口点。
//

//堆排序思想(升序):先建立大顶堆,把最大的顶拉倒最后边,再进行堆调整
#include "stdafx.h"
void AjustHeap(int a[], int count, int current)
{
	int lchild = 2*current + 1;
	int rchild = 2*current + 2;
	int max = current;
	if (lchild<=count-1 && a[lchild] > a[max])
	{
		max = lchild;
	}
	if (rchild<=count-1 && a[rchild] > a[max])
	{
		max = rchild;
	}
	if (max != current)
	{
		int temp = a[current];
		a[current] = a[max];
		a[max] = temp;

		//对变动子节点进行递归,保证大顶堆
		AjustHeap(a, count, max);
	}

}

void sort(int a[], int count)
{
	//建立大顶堆
	for (int i=count/2 - 1; i>=0; i--)
	{
		AjustHeap(a, count, i);
	}

	//不断地调整
	for (int i=count; i>=1; i--)
	{
		int temp = a[0];
		a[0] = a[i-1];
		a[i-1] = temp;

		//最后一个元素就不再参与调整了
		AjustHeap(a,i-1,0);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[10] = {5,7,4,9,0,8,1,2,6,3};
	sort(a, 10);

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