二叉堆

性质

二叉堆是完全二叉树,所以,它符合完全二叉树的性质,可以参阅http://blog.csdn.net/gykimo/article/details/8594297。

另外二叉堆(大堆)要求每个结点的值大于它所有子孙结点的值,也就是最大值就是根结点。


保持最大堆的性质

也就是判断某个结点的值是否大于它的两个孩子的大小,如果不是,则不符合最大堆性质,需要该结点和两个孩子中的较大的结点交换;交换到新位置后,还要递归判断是否符合最大堆性质。代码参考代码部分的heapify函数。


建堆

参考代码部分的build()函数。

问题一:为什么只需要处理总结点数的一半就可以生成最大堆

因为,叶子不需要执行最大堆性质,因为叶子没有孩子,自然叶子就是最大的,即符合最大堆性质,所以只需要对内结点执行最大堆性质即可。根据完全二叉树的性质得出,内结点的数量最多是总结点数的一半,所以只需要执行总结点数的一半的最大堆性质操作就可以得到最大堆。

问题二:时间复杂度

乍一看应该是O(nlogn),其实经过严格计算,复杂度为O(n),也就是可以在线性时间内完成最大堆的建立。


排序

最大堆的最大值是根结点,所以可以在O(1)时间内取出最大值,但是取出最大值后,需要一个新的结点来顶替根结点,这里一个巧妙的办法是将最后一个元素顶替根结点,然后进行保持最大堆性质操作。代码参考代码部分的sort函数。


代码

/*
 *
 * Introduction : heap sort
 * Author : Gykimo
 * Date : 20130104
 * 
 */
#ifndef _LIBS_HEAP_SORT_H
#define _LIBS_HEAP_SORT_H

#include <stdio.h>

class heapsort{
	public:
		heapsort()
			:mRoot(NULL),
			mIsMax(true),
			mSize(0){}
		
		heapsort(int * nodeList, int len, bool isMax);
		virtual ~heapsort(){}
		void sort();
	protected:
		int * mRoot;
		bool mIsMax;	/*max heap or min heap*/
		int mSize;

		void heapify(int i);
		void build();

		inline int getParent(int i){	return (i-1)>>1;	}
		inline int getLeft(int i){	return (i<<1) + 1;	}
		inline int getRight(int i){	return (i<<1) + 2;	}
		inline int getLast(){return mSize - 1;}
};

heapsort::heapsort(int * nodeList, int len, bool isMax)
	:mRoot(nodeList),
	mIsMax(isMax),
	mSize(len){
	
	build();
}

void heapsort::build(){
	for(int i = getParent(getLast()); i>=0; i--){
		heapify(i);
	}
}

void heapsort::heapify(int i){
	int tmp;

	if(mIsMax){
		int largest;
		if((getLast() >= getLeft(i)) && mRoot[i] < mRoot[getLeft(i)])
			largest = getLeft(i);
		else
			largest = i;
		
		if((getLast() >= getRight(i)) && mRoot[largest] < mRoot[getRight(i)])
			largest = getRight(i);

		if(largest != i){
			tmp = mRoot[i];
			mRoot[i] = mRoot[largest];
			mRoot[largest] = tmp;
			heapify(largest);
		}
	}else{
		int smallest;
		if((getLast() >= getLeft(i)) && mRoot[i] > mRoot[getLeft(i)])
			smallest = getLeft(i);
		else
			smallest = i;
		
		if((getLast() >= getRight(i)) && mRoot[smallest] > mRoot[getRight(i)])
			smallest = getRight(i);

		if(smallest != i){
			tmp = mRoot[i];
			mRoot[i] = mRoot[smallest];
			mRoot[smallest] = tmp;
			heapify(smallest);
		}
	}
}

void heapsort::sort(){
	int tmp;
	for(int i=getLast(); i>0; i--){
		tmp = mRoot[i];
		mRoot[i] = mRoot[0];
		printf("%d ", mRoot[i]);
		mRoot[0] = tmp;
		mSize--;
		heapify(0);
	}
	printf("%d\n", mRoot[0]);
}
#endif


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
叉堆是一种特殊的二叉树数据结构,它满足以下两个条件: 1. 父节点的值总是大于或等于(或小于或等于)其子节点的值。 2. 二叉堆是一棵完全二叉树,即除了最底层,其他层的节点个数都是满的,并且最底层的节点都尽可能地左对齐。 在Python中,我们可以使用内置的heapq模块来实现二叉堆。heapq模块提供了一些函数来操作堆,例如heappush、heappop、heapify等。 以下是一个简单的示例代码,演示如何使用heapq模块来构建和操作二叉堆: ```python import heapq # 创建一个空的二叉堆 heap = [] # 向堆中插入元素 heapq.heappush(heap, 5) heapq.heappush(heap, 2) heapq.heappush(heap, 10) heapq.heappush(heap, 1) # 弹出堆中的最小元素 min_element = heapq.heappop(heap) print(min_element) # 输出: 1 # 查看堆中的最小元素(不弹出) min_element = heap[0] print(min_element) # 输出: 2 # 将列表转换为堆 nums = [4, 8, 3, 6, 1] heapq.heapify(nums) # 弹出堆中的最小元素 min_element = heapq.heappop(nums) print(min_element) # 输出: 1 ``` 上述代码中,我们首先创建了一个空的二叉堆,然后使用heappush函数向堆中插入元素。通过heappop函数,我们可以弹出堆中的最小元素。如果只是查看最小元素而不弹出,可以直接访问heap[0]。还可以使用heapify函数将一个普通的列表转换为二叉堆。 希望这个简单的示例能帮助你理解Python中二叉堆的概念和使用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值