【数据结构与算法】最小堆 minheap

最小堆与最大堆实现思路一样,只不过顺序不同,这里只记录最小堆。

最小堆的定义是,一棵完全二叉树,每一个节点都大于等于其父节点。完全二叉树是叶子都在最后一层,且尽量靠左。

实现方面可以使用链表或者数组,这里使用数组。

如果使用数组,那么下标从0开始,父节点是i,则左子树是2*i+1,右子树是2*i+2。如果子节点是i,则父节点是(i-1)/2。

minheap的操作主要有两个,一个是add,思路是,新建一个节点在最后,然后不断地和父节点比较,如果小于父节点,就交换,直到大于等于或者root。

第二个操作是输出root,那么需要把最后一个节点移至root位置,然后重新梳理minheap,因为此时可能不再shiminheap了,梳理过程用函数minheapify实现。该函数的实现思路是传入一个i参数,表明以i为根的子树需要梳理,然后让i和比i小的子节点中的较小值交换,再递归地梳理被交换的节点。

下面是代码,这里没有考虑一些边界,比如数组的大小,或者输出空的heap的情况。

public class MinHeap {

	private int size = 0;
	private int[] heap = new int[100];
	
	public void add(int data){
		heap[size++] = data;
		int i = size - 1;
		while(i > 0 && heap[i] < heap[(i - 1) / 2]){
			swap(i, (i - 1) / 2);
			i = (i - 1) / 2;
		}
	}
	
	public int top(){
		size --;
		int r = heap[0];
		swap(size, 0);
		minheapify(0);
		return r;
	}
	
	public void minheapify(int i){
		int l = 2 * i + 1;
		int r = 2 * i + 2;
		int small = i;
		if(l < size && heap[i] > heap[l]){
			small = l;
		}
		if(r < size && heap[r] < heap[small]){
			small = r;
		}
		if(i != small){
			swap(i, small);
			minheapify(small);
		}
	}
	
	private void swap(int i, int j){
		int temp = heap[i];
		heap[i] = heap[j];
		heap[j]= temp;
	}
	
	public int size(){
		return size;
	}
}



  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用贪心算法解决最优合并问题时,需要使用一个数据结构来存储待合并的文件大小,并按照从小到大的顺序进行排序。一般来说,可以使用一个最小堆来实现这个数据结构。 在初始化最小堆时,需要将所有待合并的文件大小依次插入堆中。堆的插入操作可以使用自底向上的方式进行,即先将新元素插入到堆的最后一个位置,然后不断将其与父节点比较,如果比父节点小则交换位置,直到插入的元素比其父节点大或者到达了堆的根节点为止。 具体的代码实现可以参考以下伪代码: ``` // 定义一个最小堆 class MinHeap { private: vector<int> heap; // 存储堆的数组 public: // 将新元素插入堆中 void insert(int val) { heap.push_back(val); // 先将元素插入到数组最后一个位置 int i = heap.size() - 1; while (i > 0 && heap[i] < heap[(i-1)/2]) { // 不断将元素与其父节点比较 swap(heap[i], heap[(i-1)/2]); // 如果比父节点小则交换位置 i = (i-1)/2; } } // 从堆中弹出最小元素 int extractMin() { int res = heap[0]; heap[0] = heap.back(); // 将最后一个元素放到堆顶 heap.pop_back(); // 删除最后一个元素 int i = 0; int n = heap.size(); while (2*i+1 < n) { // 不断将堆顶元素与其左右儿子比较 int j = 2*i+1; if (j+1 < n && heap[j+1] < heap[j]) { j++; } if (heap[i] > heap[j]) { // 如果比左右儿子中的最小值大则交换位置 swap(heap[i], heap[j]); i = j; } else { break; } } return res; } }; ``` 使用以上代码可以初始化一个最小堆,其中 insert 方法用于插入新元素,extractMin 方法用于弹出最小元素。在解决最优合并问题时,只需要不断地从最小堆中弹出两个最小的文件大小进行合并即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值