ReviewForJob——堆排序

【0】README
1)本文旨在给出 推排序的源码实现;堆排序是基于二叉树的数组实现的;

【1】堆排序步骤
step1)对排序数据建堆,执行 n 次 insert 操作(基于上滤操作);每次 insert 包括 将 新元素插入到堆末尾,然后执行 上滤操作;
step2)执行 n 次 deleteMin 操作(基于下滤操作),每一次 deleteMin 操作都包含 将 堆的根元素 和 堆最后一个元素交换,并对根 执行 下滤操作;
step3)经过 deleteMin 操作后, 堆所在的数组中的元素是 逆序的;
Conclusion)由此可见,堆排序的关键操作是 上滤操作 和 下滤操作;


1)insert插入操作(基于上滤操作)
// 插入操作 based on 上滤操作.
void insert(BinaryHeap heap, ElementType data)
{
	if(heap->size == heap->capacity-1)
	{
		Error("failed insert() for heap is full.");
	}	
	percolateUp(heap, data);
}

// 上滤操作(key operation)
void percolateUp(BinaryHeap heap, ElementType data)
{
	int i;
		
	// 必须将size++.
	for(i=++heap->size; data < heap->array[i/2]; i/=2)
	{
		heap->array[i] = heap->array[i/2];
	}
	heap->array[i] = data;
}
2)deleteMin操作(基于下滤操作)
// delete minimal from heap based on percolateDown().
void deleteMin(BinaryHeap heap)
{	
	if(heap->size==0)
	{
		Error("failed deleteMin() for the heap is empty");
		return ;
	}	
	swap(&heap->array[1], &heap->array[heap->size--]); // 将二叉堆的根和二叉堆的最后一个元素交换,size--。
	percolateDown(heap, 1); // 执行下滤操作.
}

// 下滤操作(key operation)
void percolateDown(BinaryHeap heap, int i)
{
	int child;
	int temp;	

	for(temp=heap->array[i]; (child=leftChild(i))<=heap->size; i=child)
	{				
		if(child<heap->size && heap->array[child] > heap->array[child+1])
		{
			child++;
		}
		if(temp > heap->array[child]) // 比较是和 temp=heap->array[index] 进行比较.
		{			
			heap->array[i] = heap->array[child];
		}
		else
		{					
			break;
		}
	}
	heap->array[i] = temp;	
}

int leftChild(int index)
{
	return 2*index;
}

// swap a and b.
void swap(ElementType* a, ElementType* b)
{
	ElementType t;

	t = *a;
	*a = *b;
	*b = t;
}
对以上代码的分析(Analysis):(最难实现的就是 下滤操作)
A1)第21行 的 child<heap->size 是必须需要的,不要认为 它 和 第19行的 (child=leftChild(i))<=heap->size 雷同了,因为有可能 该节点只有左孩子,而没有右孩子;
A2)如下图所示,size=4的堆:节点53就只有左孩子而没有右孩子,所以第21行是不需要执行的,这通过 child<heap->size 来控制;


3)打印结果



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值