堆排序

堆:

堆的性质:(二叉)堆数据结构是一种数组对象,它可以被视为一棵完全二叉树。树中每个结点与数组中存放该结点值的那个元素对应。树的每一层都是填满,最后一层可能除外(最后 一层从一个结点的左子树开始填)。表示堆的数组A是一个具有两个属性的对象:length[A]是数组中元素的个数,heap-size[A]是存放在A中的堆的元素个数。就是说,虽然A[1...length[A]]中都可以包含有效值,但A[heap-size[A]]之后的元素都不属于相应的堆,此处heap-size[A]<=length[A]。树的为A[1]。树的根为A[1]。(摘自《算法导论》)

 

堆排序基本原理:

先建一个最大堆或者最小堆,然后再把最后一个元素与树根交换,heap-szie减一,从而缩小堆的大小,被交换出去的树根是所有元素中的最大值或者最小值,堆外的元素为已排序元素。然后用Heapify对新树根保持堆性质。依此类推,直到堆剩下一个元素。

 

时间复杂度:O(nlgn)

 

代码实现():

#include<stdio.h>


#define N 50 
#define INIFINE -10000
#define LEFT(i) (2*(i))   //use the "<<" or ">>" will be TLE
#define RIGHT(i) (2*(i)+1) 
#define PARENT(i) ((i)/2) 

int nHeapSize = 0 ;
int nLength = 0 ;

void MaxHeapify(int *A,int i) ; //保持堆性质的一个最重要的过程 
void BuildMaxHeap(int *A) ;
void HeapSort(int *A) ;
int HeapDelete(int *A,int i) ;  //练习题6.5-7,未测试

int HeapMaximun(int *A) ;    //返回堆的最大值,未测试 
int HeapExtractMax(int *A) ;   //返回堆的最大值,并将之去除
void HeapIncreaseKey(int *A,int i,int nKey) ;    //增加某个结点的关键字的值
void MaxHeapInsert(int *A,int nKey) ;  //向堆插入新的元素

int main(void)
{
	int i,n ;
	int A[N] ;

	freopen("in.txt","r",stdin) ;	

	while(scanf("%d",&n) != EOF )
	{
		nLength = 0 ;
		nHeapSize = 0 ;

		for(i = 1 ; i <= n ; i++)
		{
			scanf("%d",&A[i]) ;
			nLength++ ;
		}

		printf("You had input the List:\n") ;

		for(i = 1 ; i <= n ; ++i)
		{
			printf("%-3d",A[i]) ;
		}
		printf("\n") ;

		HeapSort(A) ;
		printf("After Sort:\n") ;
		for(i = 1 ; i <= n ; ++i)
		{
			printf("%-3d",A[i]) ;
		}
		printf("\n\n") ;
	}
	return 0 ;
}


int HeapDelete(int *A,int i) //like the HeapSort function
{
	int nTemp ;
	nTemp = A[i] ;
	A[i] = A[nHeapSize] ;
	A[nHeapSize] = nTemp ;
	nHeapSize-- ;

	MaxHeapify(A,i) ;
	return nTemp ;
}
 
void HeapInsert(int *A,int nKey)
{
	nHeapSize++ ;
	A[nHeapSize] = -INIFINE ; //aim to keep the heap attribute
	HeapIncreaseKey(A,nHeapSize,nKey) ;
}

void HeapIncreaseKey(int *A,int i,int nKey)
{
	int nTemp = 0 ;
	if(nKey < A[i])
	{
		return ;
	}

	A[i] = nKey ;

	while(i > 1 && A[PARENT(i)] < A[i])
	{
		nTemp = A[i] ;	
		A[i] = A[PARENT(i)] ;
		A[PARENT(i)] = nTemp ;
		i = PARENT(i) ;
	}
}

int HeapExtractMax(int *A) 
{
	int nMax = 0 ;
	if(nHeapSize < 1)
	{
		return -1 ;
	}
	nMax = A[1] ;
	A[1] = A[nHeapSize] ;
	nHeapSize-- ;
	MaxHeapify(A,1) ;
	return nMax ;
}
int HeapMaximun(int *A)
{
	return A[1] ;	
}

void HeapSort(int *A) 
{
	int i,nTemp ; 
	BuildMaxHeap(A) ;

	for(i = nLength ; i >= 2 ; --i)
	{
		nTemp = A[i] ;	
		A[i] = A[1] ;
		A[1] = nTemp ; 
		nHeapSize-- ;

		MaxHeapify(A,1) ;
	}
}

void BuildMaxHeap(int *A)
{
	int i ;
	nHeapSize = nLength ; //

	for(i = nLength/2 ; i >= 1 ; --i)
	{
		MaxHeapify(A,i) ;	
	}
}


void MaxHeapify(int *A,int i) 
{
	int l,r,nTemp,nLargest ; 
	l = LEFT(i) ;
	r = RIGHT(i) ;

	if(l <= nHeapSize && A[i] < A[l])
	{
		nLargest = l ;
	}
	else
	{
		nLargest = i ;
	}

	if(r <= nHeapSize && A[nLargest] < A[r] )
	{
		nLargest = r ;
	}

	if(i != nLargest)
	{
		nTemp = A[i] ;
		A[i] = A[nLargest] ;
		A[nLargest] = nTemp ;
		MaxHeapify(A,nLargest) ;	
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值