ADT - heap(堆)

二叉堆:

  以前写过二叉堆,但很少使用,快忘了。最近又查了一些关于堆的资料,于是重新熟悉一下这种数据结构。

  一个快速又简单的方式建立二叉堆,仅使用简单vector(或者数组也行):

#include "stdafx.h"
#include <iostream>
#include <vector>

#define LeftChild(i) (2*(i) + 1)
#define RightChild(i) (2*((i) + 1))

template<class T>
void swap(T & a, T & b)
{
	T tem = a;
	a = b;
	b = tem;
}

class Heap {
public:
	/* 上滤插入 */
	void up_insert(int val, std::vector<int> & values, int top);

	/* 调用上滤插入建立堆 */
	void up2build(std::vector<int> & values);

	/* 下滤插入 */
	void down_insert(std::vector<int> & values, int i, int size);

	/* 调用下滤插入建立堆 */
	void down2build(std::vector<int> & values);

	/* 堆排序 */
	void sort(std::vector<int> & values);
};

void Heap::up_insert(int val, std::vector<int> & values, int top)
{
	size_t i;
	for (i = top; i > 0 && values[i >> 1] < val; i >>= 1)
		values[i] = values[i >> 1];
	values[i] = val;
}

void Heap::up2build(std::vector<int> & values)
{
	int top = 0;
	for (auto v : values)
	{
		up_insert(v, values, top);
		++top;
	}
}

void Heap::down_insert(std::vector<int> & values, int i, int size)
{
	int last = values[i];
	for (int Child; LeftChild(i) < size; i = Child)
	{
		Child = LeftChild(i);
		if (Child != size - 1 && values[Child + 1] > values[Child])
			Child++;

		if (last < values[Child])
			values[i] = values[Child];
		else
			break;
	}
	values[i] = last;
}

void Heap::down2build(std::vector<int> & values)
{
	int size = values.size() - 1;
	for (int i = size >> 1; i >= 0; i--)
	{
		down_insert(values, i, size);
	}
}

void Heap::sort(std::vector<int> & values)
{
	int size = values.size() - 1;
	down2build(values);
	for (int i = size; i > 0; i--)
	{
		swap(values[0], values[i]);
		down_insert(values, 0, i);
	}
}

int main()
{
	Heap heap;
	std::vector<int> values { 5345,332,2341,498,248,89,239,4825,8,43,9892,872,1843 };
	
	//heap.build(values);
	heap.sort(values);

	for (auto v : values)
		std::cout << v << std::endl;
	
	getchar();
	return 0;
}

  up_build是形如‘上滤’的过程,平均情况时间复杂度为θ(n),因为up_insert函数只花费θ(1)的平均时间,最坏情况为O(lgn),空间复杂度O(1);

  down_build是形如‘下滤’的过程,时间复杂度为O(n),空间复杂度O(1),虽然有点不可思议,但详细证明见书《数据结构与算法分析》以及知乎相关问题

 左式堆:

  左式堆的性质:任意节点的左孩子的NPL(null path length - 零路径长)至少等于右孩子的NPL,这样的条件使得左式堆十分不平衡。左式堆的基本操作是进行堆合并。

  NPL的定义:任一节点到叶节点的最短路径的长。

  参考资料:

    1.《数据结构与算法分析》第6章 - 堆。

    2.知乎相关问题

扫描二维码关注公众号,回复: 87916 查看本文章

猜你喜欢

转载自www.cnblogs.com/darkchii/p/8542145.html
ADT
今日推荐