堆在计算机中的作用,堆(数据结构)_百度百科

本文探讨了堆(Heap)在计算机科学中的核心概念,包括其定义、不同类型(如最大堆和最小堆)、常见实现如二叉堆和斐波那契堆,以及堆在排序、优先级队列中的关键作用。详细介绍了堆的构造过程和算法,以及C++和VB.NET的代码实例。
摘要由CSDN通过智能技术生成

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。

中文名

堆外文名

heap

定    义

一类数据结构的统称

堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:堆中某个结点的值总是不大于或不小于其父结点的值;

堆总是一棵完全二叉树。

将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

堆是非线性数据结构,相当于一维数组,有两个直接后继。

堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。

(e2db95330de7a0b2d5a7b01beb7e41db.svg06157ee5ada50d9da3c978732ffe058c.svg)或者(3fe8b2382b81440c8ae7210f5a1382a8.svg), (232f87c3ad081df5c08cd9bd455013ff.svg)

若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

堆STL

编辑

语音

堆的STL包含于#include 

头文件中。

堆的STL支持以下的基本操作:make_heap(first, last, comp);

建立一个空堆;push_heap(first, last, comp);

向堆中插入一个新元素;top_heap(first, last, comp);

获取当前堆顶元素的值;sort_heap(first, last, comp);

对当前堆进行排序;

堆算法思想

编辑

语音

不必将值一个个地插入堆中,通过交换形成堆。假设一个小根堆的左、右子树都已是堆,并且根的元素名为1b4d3f1bdfb482b5a50f5a937306e1a5.svg ,其左右子结点为1d301fd147aca7b91c3a384bd8217f7c.svg4824b45fa601cdb557e24af2f4cb0b8e.svg ,这种情况下,有两种可能:

(1)429110fd99023efe77986da7062f32df.svg 并且a47d7c7be33b3c2d98d304366cd935dd.svg ,此时堆已完成;

(2)c8973e2bfb8ab917acdef113011d7cac.svg 或者087eb454bb50055eef2413d71bed5014.svg ,此时1b4d3f1bdfb482b5a50f5a937306e1a5.svg 应与两个子女中值较小的一个交换,结果得到一个堆,除非1b4d3f1bdfb482b5a50f5a937306e1a5.svg 仍然大于其新子女的一个或全部的两个。这种情况下,我们只需简单地继续这种将1b4d3f1bdfb482b5a50f5a937306e1a5.svg “拉下来”的过程,直至到达某一个层使它小于它的子女,或者它成了叶结点。

堆筛选法

编辑

语音

首先将要排序的所有关键码放到一棵完全二叉树的各个结点中(这时的完全二叉树并不具备堆的特性)。显然,所有的结点8cabac8746877b96a6c94d9522b77439.svg 都没有子女结点,因此以这样的8cabac8746877b96a6c94d9522b77439.svg 为根的子树已经是堆,然后从 的结点Ki开始,逐步把以为根的子树排成堆,直到以K0为根的子树排成堆,就完成了建堆过程。

在考虑将以8cabac8746877b96a6c94d9522b77439.svg 为根的子树排成堆时,以5cf4f0728e8bca16b24613cc49658bca.svg 为根的子树已经是堆,所以这时如果有eaabd95b81c50230e5e350b5bac452fb.svg5384134fe481d81c1e91b936e6894774.svg ,则不必改变任何结点的位置,以8cabac8746877b96a6c94d9522b77439.svg 为根的子树就已经是堆;否则就要适当调整子树中结点的位置以满足堆的定义。由于Ki的左、右子树都已经是堆,根结点是堆中最小的结点,所以调整后8cabac8746877b96a6c94d9522b77439.svg 的值必定是原来0f2a6b900b47df413a58a8db1e8f6e0f.svgf34a3573c3c579287863c7d503933a78.svg 中较小的一个。假设f34a3573c3c579287863c7d503933a78.svg 较小,将8cabac8746877b96a6c94d9522b77439.svgf34a3573c3c579287863c7d503933a78.svg 交换位置,这样调整后eaabd95b81c50230e5e350b5bac452fb.svg5384134fe481d81c1e91b936e6894774.svg,并且以0f2a6b900b47df413a58a8db1e8f6e0f.svg 为根的子树原来已经是堆,不必再作任何调整,只有以f34a3573c3c579287863c7d503933a78.svg为根的子树由于f34a3573c3c579287863c7d503933a78.svg的值已经发生变化(与8cabac8746877b96a6c94d9522b77439.svg交换了),所以有可能不满足堆的定义(当f34a3573c3c579287863c7d503933a78.svg的左、右子树已经是堆)。这时可重复上述过程,考虑将f34a3573c3c579287863c7d503933a78.svg以为根的子树排成堆。如此一层一层递推下去,最多可以一直进行到树叶。由于每步都保证将子树中最小的结点交换到子树的根部,所以这个过程是不会反馈的。它就像过筛一样,把最小的关键码一层一层选择出来。

堆建堆效率

编辑

语音

561ce0d0c21ba2a257cc72a28956377b.svg个结点的堆,高度014161bfbfaed69d926b956dc5554149.svg。根为第0层,则第0ca289a575808a82d9e266fdc162ba71.svg层结点个数为e5cd49fa338901c1626b7273fa97bcf3.svg,考虑一个元素在堆中向下移动的距离,这种算法时间代价为f5a1886cf2ff13d73aee4d32d363f66e.svg

由于堆有65fdec02131b9c4a5d9454be29346c43.svg层深,插入结点、删除普通元素和删除最小元素的平均时间代价和时间复杂度都是

570064815fad71e73ec2baa84a5a15cc.svg

堆代码实现

编辑

语音

c++实现#pragma once

template

class JBMinHeap

{

private:

//申请堆空间

T *_minHeap = NULL;

int _index,_maxSize;

public:

JBMinHeap(int maxSize) {

_maxSize = maxSize;

_minHeap = new T[_maxSize];

_index = -1;

}

JBMinHeap(JBMinHeap &h) {

_index = h._index;

_maxSize = h._maxSize;

_minHeap = new T[_maxSize];

for (int i = 0;i<_maxsize>

*_minHeap[i] = *h._minHeap[i];

}

}

~JBMinHeap() {

delete[]_minHeap;

}

//获取整个最小堆的头部指针

T * getMinHeap() {

return _minHeap;

}

//判断堆是不是空的

bool isEmpty() {

return _index == -1;

}

bool add(T x) {

if (isFull()) {

return false;

}

_index++;

_minHeap[_index] = x;

return true;

}

bool isFull() {

return _index == _maxSize;

}

//堆进行向下调整

void adjustDown(int index);

//队进行向上调整

void adjustUp(int index);

//建堆运算

void createMinHeap() {

if (isEmpty()) {

return;

}

for (int i = (_index-1)/2;i >-1;i--) {//直接从倒数第二层 逐层向下调整

adjustDown(i);

}

}

};

template

void JBMinHeap::adjustDown(int index) {

if (isEmpty()) {

return;

}

while (index<_index>

{

T temp = _minHeap[index];//将当前索引的位置的值保存下来

int oneC = 2 * index + 1;//获取到两个孩子的位置

int twoC = 2 * index + 2;

if (oneC == _index) {//若第一个孩子是整个堆最后一个位置 则直接执行交换操作并结束执行

_minHeap[index] = _minHeap[oneC];

_minHeap[oneC] = temp;

return;

}

if (twoC >_index) {//如果第二个孩子的索引位置越界 结束执行

return;

}

if (_minHeap[oneC] <= _minHeap[twoC]) {//正常情况的数据交互执行

if (temp > _minHeap[oneC]) {

_minHeap[index] = _minHeap[oneC];

_minHeap[oneC] = temp;

index = oneC;

}

else {//如果该处索引值已经是比两个孩子小 则结束循环

index = _index;

}

}

else

{

if (temp > _minHeap[twoC]) {

_minHeap[index] = _minHeap[twoC];

_minHeap[twoC] = temp;

index = twoC;

}

else

{

index = _index;

}

}

}

}

template

void JBMinHeap::adjustUp(int index) {

if (index > _index) {//大于堆的最大值直接return

return;

}

while (index>-1)

{

T temp = _minHeap[index];

int father = (index - 1) / 2;

if (father >= 0) {//如果索引没有出界就执行想要的操作

if (temp 

_minHeap[index] = _minHeap[father];

_minHeap[father] = temp;

index=father;

}

else {//若果已经是比父亲大 则直接结束循环

index = -1;

}

}

else//出界就结束循环

{

index = -1;

}

}

}

VB.net实现Public Class Priority_Queue

Friend Element() As Integer

Friend point As Integer ReadOnly Property Top As Integer

Get

Try

Return Element(1)

Catch ex As Exception

Return 0

End Try

End Get

End Property

ReadOnly Property Size As Integer

Get

Return point

End Get

End Property

ReadOnly Property Empty As Boolean

Get

If point = 0 Then Return True

Return False

End Get

End Property Sub push(ByVal _ele_val As Integer)

point += 1

Element(point) = _ele_val

Dim Now As Integer = point

Dim Nxt As Integer = Now / 2

While (Now <> 1 AndAlso Element(Now) > Element(Nxt))

Swap(Element(Now), Element(Nxt))

Now = Nxt

Nxt /= 2

End While

End Sub

Sub pop()

Dim now As Integer = 1 Element(1) = Element(point)

point -= 1 While (1) Dim left As Integer = 0

Dim right As Integer = 0 If (now * 2 <= point) Then

left = Element(now * 2)

End If

If (now * 2 + 1 <= point) Then

right = Element(now * 2 + 1)

End If If (right = left And right = 0) Then

Exit Sub

End If If (Element(now) 

If left > right Then

Swap(Element(now), Element(now * 2))

now *= 2

Else

Swap(Element(now), Element(now * 2 + 1))

now *= 2

now += 1

End If

Else

Exit While

End If

End While End Sub Sub New(ByVal _size As Integer)

ReDim Element(_size)

point = 0

End Sub

Protected Overrides Sub Finalize()

MyBase.Finalize()

End Sub End Class

词条图册

更多图册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值