堆排序C语言实现

1.堆,堆实际上是一棵完全二叉树,堆分为大顶堆和小顶堆。大顶堆需要满足性质:Key[i]>=Key[2i+1]&&key>=key[2i+2];小顶堆需要满足性质:Key[i]<=key[2i+1]&&Key[i]<=key[2i+2],即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

2.堆排序一般分为三个过程:

建堆(初始化堆):从一个数组顺序读取元素,建立一个堆(完全二叉树)

调整堆:将堆进行调整,使得堆顶为最大(最大堆)或者最小(最小堆)的元素

堆排序和维护堆:将堆顶元素出堆后,需要将堆的最后一个节点补充到堆顶,因为这样破坏了堆的秩序,所以需要进行维护。


下面举例说明堆排序的过程(以大顶堆为例):

给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。

1、首先根据该数组元素构建一个完全二叉树,得到


2、然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

首先从(heapsize(堆的长度)-2)/2,即3开始进行调整堆,3和8交换,见下图

然后从7开始进行调整,7和20交换,见下图

然后,进行16和20的交换,20和16交换后导致16不满足堆的性质,因此需重新调整,如下图

这样就得到了初始堆,如下图

3、进行堆排序

得到有序堆。

   从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。

以上信息参考http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

C语言实现代码如下:

#include 

void buildMaxHeap(int [],int);
void maxHeap(int [],int,int);
void heapSort(int [],int);
int getParentNode(int);
int getLeftChildNode(int);
int getRightChildNode(int);
void print(int [],int);

int getParentNode(int current)
{
	return (current-1) >> 1;//current-1右移一位,相当于除以2,也可写成floor((current-1)/2)
}

int getLeftChildNode(int current)
{
	return (current << 1) + 1;//current左移一位,相当于乘以2,也可写成2*current+1
}

int getRightChildNode(int current)
{
	return (current << 1) + 2;
}

void buildMaxHeap(int data[],int heapsize)//堆排序第一步,建堆,并调整其为最大堆
{
	int startParentNode = getParentNode(heapsize-1);
	for (int i = startParentNode;i >= 0;i--)
	{
		maxHeap(data,heapsize,i);
	}
}

void maxHeap(int data[],int heapsize,int current)//堆排序第二步,调整堆,将非最大堆调整成最大堆
{
	int leftChild = getLeftChildNode(current);
	int rightChild = getRightChildNode(current);
	int largest = current;

	if (leftChild < heapsize && data[leftChild] > data[current])
	{
		largest = leftChild;
	}
	if (rightChild < heapsize && data[rightChild] > data[largest])
	{
		largest = rightChild;
	}

	if (largest != current)
	{
		int tmp;
		tmp = data[current];
		data[current] = data[largest];
		data[largest] = tmp;
		maxHeap(data,heapsize,largest);
	}
}

void heapSort(int data[],int heapsize)//堆排序第三步,堆排序,堆顶不断与堆末尾的数交换,然后调整堆,最后得到有序堆。
{
	buildMaxHeap(data,heapsize);
	for (int i = heapsize-1;i > 0;i--)
	{
		int tmp = data[0];
		data[0] = data[i];
		data[i] = tmp;
		maxHeap(data,i,0);
	}
	print(data,heapsize);
}

void print(int data[],int heapsize)
{
	for (int i = 0;i < heapsize;i++)
	{
		printf("%d ",data[i]);
	}
	printf("\n");
}

int main()
{
	int data[]={16,7,3,20,17,8};
	int num = sizeof(data)/sizeof(int);
	printf("----------堆排序----------\n");
	print(data,num);
	heapSort(data,num);

	return 0;
}


 
 

你可能感兴趣的:(C/C++)