堆(Heap)
两种简单实现
第一种 链表
第一种实现利用链表存储数据,每次在表头插入元素;getMin 时,遍历一遍线性表找到最小的元素,然后将之删除、值返回。(getMax 同理)。
链表的在头节点的插入和删除时间复杂度都是O(1),所以用链表实现的堆,insert 时间复杂度是O(1)、getMin 时间复杂度是O(n)。
C++代码如下
template<typename T>
class Heap
{
public:
void insert(const T &val)
{
l.push_front(val);
} T getMin()
{
list<T>::iterator itMin = l.begin(); for (list<T>::iterator it = l.begin(); it != l.end(); it++)
{
if (*it < *itMin)
itMin = it;
} T temp = *itMin; l.erase(itMin); return temp;
} private:
list<T> l;
};
测试用例如下
int main()
{
Heap<int> h; h.insert();
h.insert();
h.insert();
h.insert(); cout << h.getMin() << endl; return ;
}
第二种 二叉树
第二种实现利用二叉树来存储元素,它对于 insert 和 getMin 操作时间复杂度都是 O(log N)。
C++代码如下
template<typename T>
struct Node
{
Node(T v) : val(v), left(nullptr), right(nullptr) {};
T val;
struct Node* left;
struct Node* right;
}; template<typename T>
class Heap
{
public:
Heap() { root = nullptr; } void insert(const T &val)
{
struct Node<T> **p = &root; while (*p != nullptr)
{
if (val == (*p)->val)
return; if (val < (*p)->val)
{
p = &((*p)->left);
continue;
} if (val >(*p)->val)
{
p = &((*p)->right);
continue;
}
} *p = new struct Node<T>(val);
} T getMin()
{
struct Node<T> *p = findMin(root); T temp = p->val; erase(p); return temp;
} private:
struct Node<T>* findMin(struct Node<T>* p)
{
if (p != nullptr)
while (p->left != nullptr)
p = p->left; return p;
} struct Node<T>* findFather(T val)
{
struct Node<T>* p = root; while (p != nullptr)
{
if (p->val > val)
{
if (p->left->val == val)
break; p = p->left;
} if (p->val < val)
{
if (p->right->val == val)
break; p = p->right;
} if (p->val == val)
break;
} return p;
} void erase(struct Node<T>* p)
{
struct Node<T>* fatherP = findFather(p->val); if (p == root)
{
if (p->left == nullptr && p->right == nullptr)
{
root = nullptr;
delete p;
} //right
else if (p->left == nullptr && p->right != nullptr)
{
root = p->right;
delete p;
}
} //leaf
else if (p->left == nullptr && p->right == nullptr)
{
if (fatherP->left == p)
fatherP->left = nullptr; if (fatherP->right == p)
fatherP->right = nullptr; delete p;
} //right child
else if (p->left == nullptr && p->right != nullptr)
{
fatherP->left = p->right;
delete p;
}
} struct Node<T>* root;
};
测试用例如下
int main()
{
Heap<int> bt; for (auto &e : { })
bt.insert(e); for (auto &e : { })
cout << bt.getMin() << endl; for (auto &e : { , , })
bt.insert(e); for (auto &e : { , , })
cout << bt.getMin() << endl; for (auto &e : { , , })
bt.insert(e); for (auto &e : { , , })
cout << bt.getMin() << endl; for (auto &e : { , , , , , , })
bt.insert(e); for (auto &e : { , , , , , , })
cout << bt.getMin() << endl; return ;
}
二叉堆
二叉堆是“堆”的默认实现方式。
堆结构两大性质
i. 结构性质
对于数组中任一位置 i 上的元素,其左儿子在位置 2i 上,右儿子在左儿子后的单元 (2i + 1)中,它的父亲则在位置 ⌊i / 2⌋ 上。
i. 堆序性质
在一个堆中,对于每一个节点 X, X 的父亲中的关键字小于(或等于)X 中的关键字,根节点除外(它没有父亲)。
代码实现
#include <iostream>
#include <vector> using namespace std; template<typename T>
class Heap
{
public:
Heap() : _v() {}; void insert(T val)
{
_v.push_back(val); vector<T>::size_type i; for (i = _v.size() - ; _v[i / ] > val; i /= )
{
_v[i] = _v[i / ];
} _v[i] = val;
} T removeMin()
{
if (_v.size() == )
{
return NULL;
} T minElement = _v[];
T lastElement = _v[_v.size() - ]; vector<T>::size_type i, child; for (i = ; i * < _v.size(); i = child)
{
child = i * ; if (child != _v.size() - && _v[child + ] < _v[child])
{
child++;
} if (lastElement > _v[child])
{
_v[i] = _v[child];
}
else
{
break;
}
} _v[i] = lastElement;
_v.pop_back(); return minElement;
} private:
vector<T> _v;
}; int main()
{
int arr[] = { ,,,, }; Heap<int> h; for (auto e : arr)
{
h.insert(e);
} for (auto e : arr)
{
cout << h.removeMin() << endl;
} return ;
}
d-堆
d-堆是二叉堆的简单推广,它恰像一个二叉堆,只是所有节点都有 d 个儿子(因此,二叉堆是2-堆)。
它将 insert 操作的运行时间改进为 O(logd N)。然而,对于大的 d,deleteMin操作费时得多。
有证据显示,在实践中 4-堆 可以胜过二叉堆。
堆(Heap)的更多相关文章
- JVM的堆(heap)、栈(stack)和方法区(method)
JVM主要由类加载器子系统.运行时数据区(内存空间).执行引擎以及与本地方法接口等组成.其中运行时数据区又由方法区Method Area.堆Heap.Java stack.PC寄存器.本地方法栈组成. ...
- [转]JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )
这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有比较大的帮助.废话不想讲了.入主题: 先了解具体的概念:JAVA的JVM的内存可分为3个区:堆(h ...
- 堆heap和栈Stack(百科)
堆heap和栈Stack 在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈 ...
- (转)Java里的堆(heap)栈(stack)和方法区(method)(精华帖,多读读)
[color=red][/color]<一> 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收. 引用数据类型,需要用new来创建,既在栈 ...
- Java中堆(heap)和栈(stack)的区别
简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分 ...
- 优先队列Priority Queue和堆Heap
对COMP20003中的Priority queue部分进行总结.图片来自于COMP20003 queue队列,顾名思义特点先进先出 priority queue优先队列,出来的顺序按照优先级prio ...
- python数据结构之堆(heap)
本篇学习内容为堆的性质.python实现插入与删除操作.堆复杂度表.python内置方法生成堆. 区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙:而栈像一个直立垃圾桶,一列下 ...
- 纸上谈兵: 堆 (heap)
纸上谈兵: 堆 (heap) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority ...
- JVM 内存初学 堆(heap)、栈(stack)和方法区(method)
这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有比较大的帮助.废话不想讲了.入主题:先了解具体的概念:JAVA的JVM的内存可分为3个区:堆(he ...
- 转:JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )
原文地址:JVM 内存初学 (堆(heap).栈(stack)和方法区(method) ) 博主推荐 深入浅出JVM 这本书 先了解具体的概念:JAVA的JVM的内存可分为3个区:堆(heap).栈( ...
随机推荐
- POJ-2353 Ministry(动态规划)
Ministry Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4761 Accepted: 1528 Special Judg ...
- java 中方法的重写
方法的重写 1.在子类中可以根据需要对从基类中继承来的方法进行重写. 2.方法重写必须要和被重写方法具有相同方法名称.参数列表和返回类型. 3.重写方法不能使用比被重写方法更严格的访问权限 4.注意与 ...
- SS iproute2,nslookup,dig
从某种意义上说,iproute工具集几乎可以替代掉net-tools工具集,具体的替代方案是这样的:用途 net-tool(被淘汰) iproute2地址和链路配置 ifconfig ip ...
- Vue源码学习1——Vue构造函数
Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...
- SPARQL 入门教程
1.准备工作 1.1 下载ZIP 1.2 配置环境变量 1.3 查询文件 vc-db-1.rdf 2. 查询操作 2.1 普通查询 /** * 查询family为"Smith"的 ...
- Python开发【笔记】:加锁的最佳方案
避开死锁 代码程序中,尽量要避免死锁的产生,下面分析常见的线程锁使用方式 :注:只有同一把锁才会产生互斥 1.常见的死锁方式(加锁时程序报错,锁未释放): import time import thr ...
- dedecms批量导出新增文章url和标题
百度站长工具推出主动提交功能有一段时间了,可以将新产出链接立即通过此方式推送给百度,以保证新链接可以及时被百度收录.那么dedecms如何批量导出新增文章url呢?你可以用标签调用最新文章,可以用sq ...
- HTML5插件
HTML 助手(插件) 辅助应用程序(helper application)是可由浏览器启动的程序.辅助应用程序也称为插件. 辅助程序可用于播放音频和视频(以及其他).辅助程序是使用 <obje ...
- SQL 4
SQL WHERE 子句 WHERE 子句用于过滤记录. SQL WHERE 子句 WHERE 子句用于提取那些满足指定标准的记录. SQL WHERE 语法 SELECT column_name,c ...
- vue学习之node.js
Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装.本文详细介绍了No ...