1. 程式人生 > >ADT - heap(堆)

ADT - heap(堆)

str com define 合並 iostream color 進行 建堆 nbsp

二叉堆:

  以前寫過二叉堆,但很少使用,快忘了。最近又查了一些關於堆的資料,於是重新熟悉一下這種數據結構。

  一個快速又簡單的方式建立二叉堆,僅使用簡單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(n),空間復雜度O(1);

  down_build是形如‘下濾’的過程,時間復雜度為O(n),空間復雜度O(1),有點不可思議,不過這裏《數據結構與算法分析》書中說下濾建堆也是O(n),但知乎上有證明下濾是O(nlgn) = = 難道是我看錯了?其實我也覺得自頂向下建堆的復雜度為O(nlgn))

左式堆:

  左式堆的性質:任意節點的左孩子的NPL(null path length - 零路徑長)至少等於右孩子的NPL,這樣的條件使得左式堆十分不平衡。左式堆的基本操作是進行堆合並。

  NPL的定義:任一節點到葉節點的最短路徑的長。

  參考資料:

    1.《數據結構與算法分析》第6章 - 堆。

    2.知乎相關問題

ADT - heap(堆)