`
evasiu
  • 浏览: 171457 次
  • 性别: Icon_minigender_2
  • 来自: 广州
博客专栏
Fa47b089-e026-399c-b770-017349f619d5
TCP/IP详解卷一>阅读...
浏览量:12649
社区版块
存档分类
最新评论

编程珠玑 -- 关于堆

 
阅读更多

堆是这样一种数据结构,它首先是一棵二叉树,而且还是一棵完全二叉树;其次,对于最小堆,父节点的值小于子节点。
有两种特殊要求的二叉树,一种是完全二叉树,一种是满二叉树。完全二叉树添加叶子节点的时候,要求从左到右添加,所以如果左子树没有被填满,就不会把叶子结点添加到右子树上。满二叉树则要求一个节点要么有两个孩子,要么就没有孩子。他们的形状如下:


 
完全二叉树的性质使我们可以使用一个数组来表达一棵完全二叉树,因为叶子结点加入到树的位置是固定的,所以我们可以通过下标找到他的父节点或子节点(如果有的话)。令根的下标为1,则对于节点i,其父结点下标为i/2,孩子节点下标分别为i*2和i*2+1.
堆有两个重要的操作,可以用于构建堆或维持堆的性质,他们分别为shiftup和shiftdown。shiftup(int n)操作的前提是数组X[1,n-1]满足堆的性质,经过该操作后,X[1,n]满足堆的性质。shiftdown(int n)操作的前提是数组X[2,n]满足堆的性质,经过该操作后X[1,n]满足堆的性质。关于shiftup,因为X[1,n-1]已经满足堆的性质,所以对于新加入的元素X[n],只需要沿着其父节点往上交换,直到遇一个比他小的父节点或者直到他已经到了根节点的位置。与shiftup相反,shiftdown则将沿着孩子节点的方向往下交换,但是与shiftup不同的时,他这时候可能面临两个选择,只要父节点比他的孩子节点中比较小的孩子节点大,那么就将进行交换。它们的实现如下:

 

//precondition: heap[1,n-1]
//postcondition: heap[1,n]	
void Heap::siftup( int n ){
	int i=n;
	/*while( i>1 && array[i/2]>array[i] ){
		int t = array[i];
		array[i] = array[i/2];
		array[i/2] = t;
		i = i/2;
	}*/
	int hold = array[0];
	array[0] = array[n];		//这样将不用进行是否到达根的测试
	while( array[i/2]>array[i] ){
		int t = array[i];
		array[i] = array[i/2];
		array[i/2] = t;
		i = i/2;
	}
	array[0] = hold;
}

//precondition: heap[2,n]
//postcondition: heap[1,n]
void Heap::siftdown( int n ){
	int i=1, small=i;
	while( i<=n/2 ){
		small = i*2;
		if( small+1 <= n )
			if( array[small+1] < array[small] )
				small++;
		if( array[i] <= array[small] )
			break;
		int t = array[i];
		array[i] = array[small];
		array[small] = t;
		i = small;
	}
}

//这是对siftdown(n)的一点小改动
//它将用于堆的构建中
//precondition:heap[i+1,n]
//postcondition:heap[i,n]
void Heap::siftdown( int i, int n ){
	int small;
	while( i<=n/2 ){
		small = i*2;
		if( small+1 <= n )
			if( array[small+1]<array[small] )
				small++;
		if( array[i] <= array[small] )
			break;
		int t = array[i];
		array[i] = array[small];
		array[small] = t;
		i = small;
	}
}
 

堆的一个应用是优先堆,如优先权高的先被服务,他一般包含两个操作,一个是取当前优先级最高的元素,即根节点,取出根节点后,数组X[1,n]将不再满足堆的性质,但是数组X[2,n]的仍满足,可以通过把X[n]放到X[1]处从而达到shiftdown(n-1)的前提条件,从而维持堆的性质。另一个操作是插入一个新的元素,新加入的元素n破坏了整个数组的堆性质,但是满足shiftup(n)前提,通过shiftup来维持堆的性质。优先级堆的两个操作如下:

 

void insert( int t ){
	if( size == 0 ){
		array[++size] = t;
		return;
	}
	if( size<maxlen ){
		array[++size] = t;
		siftup(size);
	}
}
int extractMin(){
	int t = array[1];
	array[1] = array[size];
	array[size] = t;
	size --;
	siftdown( size );
	return array[size+1];
}

堆的另一个应用是排序。既然每取一次就得到第i小的值,那么对一个已经建好的有n个元素的堆经过n次取值,将得到一个排好序的数组。因此除了一个取当前最小值的操作外,排序还需要对数组X[1,n]进行建堆。可以通过两个方向来构造堆。一种是从根到叶节点,数组X[1,i]从i=1开始,通过shiftup(i+1)使X[1,i+i]满足堆的性质,最后建成堆X[1,n]。另一种从叶节点到根节点。因为叶子节点都没有孩子,他们满足堆的性质,然后从最后一个父节点开始往下shiftdown,由完全二叉树的性质,可以得到最后一个父节点为n/2。

void build(){
	for( int i=size/2; i>0; i-- )
		siftdown(i, size);
}

int sort(){
	for( int i=size; i>1; i-- ){
		int t = array[1];
		array[1] = array[i];
		array[i] = t;
		siftdown( i-1 );
	}
}

 优先级堆和用于排序的堆的初始化方法可能也不一样:

class Heap{
	private:
		int size, maxlen;
		int* array;		
	public:
		//优先级堆
		Heap( int len ){
			maxlen = len;
			size = 0;
			array = new int[maxlen+1];
		}
		//排序堆
		Heap( int* a, int len ){
			array = --a;
			size = len;
			maxlen = len;
		}
		//其他操作
		//....
	};
 
  • 大小: 20.9 KB
分享到:
评论

相关推荐

    编程珠玑源码下载编程珠玑书后源代码

    《编程珠玑》是计算机科学领域的一本经典之作,由Jon Bentley 编著,它以其深入浅出的方式探讨了程序设计的问题和解决方案,尤其在数据结构、算法优化以及问题解决策略方面有着独到的见解。这本书的源代码是作者为了...

    编程珠玑(PDF带目录)

    《编程珠玑》无疑是计算机编程领域中的一块瑰宝,其作者Jon Bentley在编写时便意在创建一本能够经受时间考验的经典著作。本书以其深入浅出的讲解方式和丰富的实例,不仅为读者提供了算法领域的知识,更提供了深入...

    编程珠玑源代码

    3. **数据结构**:《编程珠玑》中会涉及到多种数据结构,如链表、树、图、堆和哈希表。源代码中会有这些数据结构的具体实现,有助于读者掌握它们的操作和特性,为解决复杂问题打下基础。 4. **问题解决技巧**:书中...

    编程珠玑pdf+源代码

    1. **排序与搜索算法**:《编程珠玑》详细讲解了各种排序算法,如插入排序、选择排序、快速排序、归并排序以及堆排序,以及它们的性能分析。同时,书中也涉及到了查找算法,如二分查找和哈希表的应用,这些都是面试...

    编程珠玑番外篇

    《编程珠玑番外篇》是由Google工程师徐宥创作的一系列关于编程语言和技术开发的深度思考文集。这个压缩包包含13篇PDF格式的文章,每一篇都蕴含着丰富的编程智慧,对于程序员和软件开发者来说,是不可多得的学习资料...

    编程珠玑中文版

    《编程珠玑》是一本经典的计算机科学与编程书籍,作者是Jon Bentley。这本书以其深入浅出的方式探讨了程序设计中的问题解决策略和算法优化,深受程序员喜爱。它不仅讲解了如何编写高效的代码,还强调了如何优雅地...

    编程珠玑pdf

    《编程珠玑》第二版,由Jon Bentley撰写,是一本被众多顶级大师推荐的经典之作,深入探讨了软件工程中令人着迷的一面——编程技巧与创新思维。本书不仅为学生提供了宝贵的指导,也对经验丰富的程序员有着重要的启示...

    编程珠玑(Programming Pearls) 第二版-- (大礼包)PDF 中文版+英文版+源码

    《编程珠玑(Programming Pearls)》是计算机科学领域中一本经典的著作,由Jon Bentley编著,第二版进一步丰富和完善了第一版的内容。这本书被誉为程序员的智慧结晶,它不仅仅是一本关于编程技巧的书,更是一本探讨...

    《编程珠玑》部分源代码Java实现

    3. **其他算法与数据结构**:除了上述内容,源代码可能还涵盖了其他经典的算法和数据结构,比如快速排序、堆排序、哈希表、二叉搜索树等,这些都是解决编程珠玑中问题的常见工具。 学习这些源代码,你不仅可以掌握...

    《编程珠玑》(Programming Pearls)课本和习题代码实现

    《编程珠玑》是计算机科学领域的一本经典著作,作者Jon Bentley通过一系列精心设计的问题和解决方案,探讨了程序设计的艺术和技巧。这本书以其独特的视角,深入浅出地讲解了算法和数据结构,以及如何优雅地解决复杂...

    编程珠玑.zip

    《编程珠玑》是计算机科学领域的一本经典著作,作者是Jon Bentley。这本书以其独特的视角,深入浅出地探讨了程序设计中的一些核心问题,并提供了许多实用的解决策略。书中的内容涵盖了算法分析、数据结构优化、编程...

    中文第二版-编程珠玑

    《编程珠玑》中涵盖了大量关于算法优化、数据结构设计、问题解决策略等方面的知识点,旨在帮助读者提升编程技巧,更好地解决实际问题。 1. **算法优化**:书中强调了算法选择和优化的重要性,通过实例解析如何在...

    计算机学科经典书籍—编程珠玑

    ### 计算机学科经典书籍—编程珠玑 #### 一、引言 《编程珠玑》作为计算机科学领域的经典之作,自问世以来一直深受广大程序员的喜爱与推崇。该书由美国著名计算机科学家Jon Bentley撰写,通过对一系列实际编程问题...

    转:编程珠玑

    《编程珠玑》是一本经典的计算机科学与编程书籍,作者是Jon Bentley。这本书以其深入浅出的方式探讨了程序设计中的各种问题和解决策略,尤其强调了数据结构、算法和问题解决技巧的重要性。在这个数字化时代,理解和...

    编程珠玑(经典)

    《编程珠玑》不仅仅是一本关于编程技术的指南,它更是对编程艺术的一种庆祝。通过深入浅出的方式,作者不仅教会了我们如何编写高效的代码,更重要的是教会了我们如何思考问题、如何创新。这本书不仅适合编程新手,也...

    programming pearls 编程珠玑 源码

    《编程珠玑》是计算机科学领域的一本经典著作,作者是Jon Bentley。这本书以其深入浅出的算法解析和实际问题的解决策略,深受程序员们的喜爱。源码是书中实例的实现,通过阅读和理解这些源码,我们可以更深入地学习...

    编程珠玑(第二版)中文版

    《编程珠玑(第二版)中文版》是程序员必读的经典之作,由Jon Bentley 编著,本电子书深入探讨了计算机科学中的诸多重要问题,尤其是数据结构、算法设计和问题解决策略。这本书以其独特的视角,将编程挑战转化为富有...

Global site tag (gtag.js) - Google Analytics