d-heap

Abstact

数据结构与算法分析:C语言描述介绍了一种数据结构:d-堆。通常的堆是二叉堆:也就是完全二叉树。d-堆是每个结点有d个儿子。这篇blog来实现d-heap.


d-heap

在二叉堆里:如果一个结点的下标是i,那么它的父亲下标是i/2,它的左儿子结点下标是2i,右儿子结点下标是2i+1。 正因为这种特殊的规律,所以二叉堆的实现非常优美(自我感觉的)
但是在d-heap里有这些规律吗?

d-heap中父亲和儿子的关系

child(i,j) = d*(i-1)+2+j    (i是父亲结点的下标,j是第几个儿子,范围是0~d-1)
parent(i) = (i-2+d)/d         
last_have_leaf = (size()+1)/d    (这是d-heap最后一个有叶子的结点。在heap里是size()/2)

上面就是d-heap中父亲和儿子的关系。
下面是我举个小栗子:
在这里插入图片描述


implement

d-heap的ADT有

void clear();   //清空堆
unsigned size()const;  // 返回堆大小
void insert(int x);     //插入元素
int findmin()const;     //返回堆顶元素
void deletemin();      //删除堆顶元素
bool isempty()const;    //堆是否为空
/*
这两个函数是以O(n)构建堆。
把输入的N个元素随意放在树中,在执行percplate(i),从结点i下滤。(percplate其实和堆排序里辅助函数是一样的,我就不详细写了)
我在构造函数里使用这两个函数。dheap(int D,const std::vector<int>& data);
*/
void buildheap();
void percplate(int);

d-heap的实现和二叉堆差不多:我就懒的写了。

#pragma once
#include<vector>
#include<initializer_list>
#include<climits>
#define MIN INT_MIN
using std::initializer_list;
class dheap
{
public:
	dheap(int D) :d(D) {
		_root.push_back(MIN);	
	}
	dheap(int D,const std::vector<int>& data);
	~dheap()=default;
	void clear();
	unsigned size()const;
	void insert(int x);
	int findmin()const;
	void deletemin();
	bool isempty()const;
private:
	int parent(int son) {
		return (son - 2 + d) / d;
	}
	int child(int parent, int time) {    //time is 0 ~ d-1
		return (time >= this->d )?-1:d * (parent - 1) + 2 + time;
	}
	void buildheap();
	void percplate(int);
	std::vector<int> _root;
	int d;
};

#include "dheap.h"
#include<algorithm>
#include<iostream>


dheap::dheap(int D, const std::vector<int>& data):d(D)
{
	_root.push_back(MIN);
	for (auto x : data)
		_root.push_back(x);
	buildheap();
}


void dheap::clear()
{
	_root.erase(_root.begin()+1,_root.end());
}


unsigned dheap::size() const
{
	return _root.size() - 1;
}

void dheap::insert(int x)
{
	_root.push_back(x);
	int i;
	for (i = size(); x < _root[this->parent(i)]; i = parent(i)) {    // 如果x的值大于父亲的值,则父亲下,
		_root[i] = _root[parent(i)];
	}
	_root[i] = x;
}

int dheap::findmin() const
{
	return isempty() ? _root[0]:_root[1] ;
}

void dheap::deletemin()
{
	if (!isempty()) {
		int minvalue = findmin(), lastvalue = _root.back(), i,_child;
		_root.pop_back();
		for (i = 1; this->child(i,0) <= this->size(); i = _child) {    // child(i,0) i的第一个孩子 ,第一个孩子小于size(),证明i有孩子
			_child = this->child(i, 0);						//找最小的孩子
			if (_child + d - 1 <= size()) 							//有d个儿子
				_child =std::distance(_root.begin(),std::min_element(_root.begin()+_child,_root.begin()+_child+d));
			else                                           //没有d个儿子 
				_child = std::distance(_root.begin(), std::min_element(_root.begin() + _child, _root.end()));
			if (lastvalue > _root[_child])
				_root[i] = _root[_child];
			else
				break;
		}
		if(this->size()!=0)
		_root[i] = lastvalue;
	}
	else
		return;
}

bool dheap::isempty() const
{
	return size() == 0 ? true: false;
}

void dheap::buildheap()
{
	for (int i = (this->size()+1)/this->d; i > 0; i--)
		this->percplate(i);
}

void dheap::percplate(int i)
{
	int temp = _root[i], _child;                                                          // i always is father
	for (_child = this->child(i,0); _child < this->size(); _child = this->child(i,0)) {     // _child is i`s son,now find min`s son
		if (_child + d - 1 <= size()) 							//有d个儿子
			_child = std::distance(_root.begin(), std::min_element(_root.begin() + _child, _root.begin() + _child + d));
		else                                           //没有d个儿子 
			_child = std::distance(_root.begin(), std::min_element(_root.begin() + _child, _root.end()));
		if (temp > _root[_child])
			_root[i] = _root[_child];  
		else
			break;
		i = _child;
	}
	_root[i] = temp;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值