导航:首页 > 源码编译 > 建堆的算法

建堆的算法

发布时间:2022-04-27 00:40:33

⑴ 求一计算机数据结构题解

以最大堆为例,给一个建堆的算法,
楼主要的保持堆的性质的算法,只要选取其中一段程序就行了~~~

//******************
// 6.3_1 建堆
// Date 2007.02.13
//******************

#include <iostream>
using namespace std;

const int maxn = 1000;

void max_heapify( int A[maxn], int i, int heap_size )
{
int l, r, largest, temp;

l = 2 * i;
r = 2 * i + 1;

if (( l <= heap_size ) && ( A[l] > A[i] ))
largest = l;
else
largest = i;
if (( r <= heap_size ) && ( A[r] > A[largest] ))
largest = r;
if ( largest != i ) {
temp = A[i];
A[i] = A[largest];
A[largest] = temp;

max_heapify( A, largest, heap_size );
}
}

void build_max_heap( int A[maxn], int n )
{
int i;

for (i = n / 2; i >= 1; i--)
max_heapify( A, i, n );
}

int main()
{
int i, n;
int A[maxn];

cin >> n;

for (i = 1; i <= n; i++)
cin >> A[i];

build_max_heap( A, n );

for (i = 1; i < n; i++)
cout << A[i] << ' ';

cout << A[n] << endl;

return 0;
}

⑵ 堆排序中建堆过程时间复杂度O(n)怎么来的

建堆算法是从最后一个非叶子结点开始下溯(即 Max-Heapify操作),也可以把建堆过程想成先对左子树建堆(T(n/2)),再对右子树建堆(T(n/2)),最后对根下溯(O(lg n))

⑶ 堆排序是怎么建堆的 关键字序列 42 13 24 91 23 16 05 88是怎样建堆的

首先把所有数据填进一个完全二叉树中。然后对非终端结点n/2向下进行调整。建小根堆的时候方法是:1.元素下调。比较它与两个孩子的大小。哪个孩子比它小也比兄弟小则把它调到那个孩子的位置。然后再判断该位置还要不要往下调。2.从n/2开始,对它之前的所有元素进行1操作。
本题解法为(按完全二叉树写)
一。把所有元素写进完全二叉树中得
42
13 24
91 23 16 05
88

二。1.对非叶子元素进行调整,即第n/2个元素,即本题的91.
因为91的孩子为88.比91小。所以调到88的位置。即91和88换
42
13 24
88 23 16 05
91

2.对n/2前一个元素进行调整。即本题的24.因为16和05都比24小,而05比16小,所以24和05调
42
13 05
88 23 16 24
91

3.对步骤2之前的一个元素,即本题的13进行调整,因为88和23都比13大,所以不用调。
4.对步骤3之前的一个元素,即本题的42进行调整。因为13和05都比42小,二05比13小。所以05和42调换位置。而调换位置后42的儿子为16和24,16比24小。所以42和16换位置。(此时已经对第一个元素进行了调整,就可以结束了,如果没错的话就是最终结果)
05
13 16
88 23 42 24
91
建的是小根堆,如果要建大根堆的话,也是往下调,但比较的是下面的哪个大。其他同理

⑷ 如何判断一个序列是否为堆

堆可以看成一棵完全二叉树:

任一根节点>=左右孩子(或者<=)(大的叫大根堆,小的叫小根堆。)注意一个堆中的这种性质有一致性,不能既有大于又有小于情况存在。

这题你应该是理解错题意了,首先,大根堆是一个完全二叉树,根节点大于左右节点,利用堆的性质来看选项A:

91为根节点,下面挂两个子节点85、53。然后以85为根节点,下面挂两个子节点36、47,以53为根节点,下面挂两个子节点30,24。

以此类推,得到选项C是正确答案。

(4)建堆的算法扩展阅读:

堆是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

1、堆中某个节点的值总是不大于或不小于其父节点的值;

2、堆总是一棵完全二叉树。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。堆是线性数据结构,相当于一维数组,有唯一后继。

一、堆的算法思想

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

(1) R的值小于或等于其两个子女,此时堆已完成;

(2) R的值大于其某一个或全部两个子女的值,此时R应与两个子女中值较小的一个交换,结果得到一个堆,除非R仍然大于其新子女的一个或全部的两个。

这种情况下,我们只需简单地继续这种将R“拉下来”的过程,直至到达某一个层使它小于它的子女,或者它成了叶结点。

二、堆的定义

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

(ki<= k2i,ki<= k2i+1)或者(ki>= k2i,ki>= k2i+1), (i = 1,2,3,4...n/2)

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

由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

⑸ 建堆的时间复杂度到底是多少

建最大堆或者最小堆都是O(N),不是O(NlogN),这个证明在算法导论第3版 88页有证明。
建立完堆后,就开始交换堆顶元素和最后一个元素,叫做出堆,出堆后需要再次维护堆顶,这一步时间复杂度是logN。

⑹ 我看书上堆排序,每次都要重新建堆,然后再调外根节点和最后一个结点,感觉这样好麻烦你们是怎么做的呢

堆排序很重要的一个步骤是初始建堆,它保证了树中的每个子树的根结点都比其下的子结点大。
建堆后的过程基本上就是选择出最大值,然后将被交换到根结点位置的结点进行下沉的过程。而这些过程虽然对树的局部结构进行了调整,但严格来说,不算是重新建堆。
《算法导论》上对堆排序讲得很详细。它把堆排序算法分成了三个子算法:
一个将结点下沉的递归算法;一个初始建堆算法和一个排序算法。
具体过程是:
1、初始建堆算法调用结点下沉递归算法完成建堆;
2、排序算法在建好的堆上得到根结点(即最大值),然后调用结点下沉的递归算法将交换到根结点位置的结点进行下沉。反复第2步,整个算法就完成了。
思路很清晰,可以去看看。

⑺ 为什么堆排序构建堆的时间复杂度是N,而重调堆的时间复杂度是logN

建堆的时候你看看是不是多次调用了调堆的函数呢,那肯定就不只是logN了,如果从底部最后的父节点开始建堆,那么我们可以大概算一下:
假如有N个节点,那么高度为H=logN,最后一层每个父节点最多只需要下调1次,倒数第二层最多只需要下调2次,顶点最多需要下调H次,而最后一层父节点共有2^(H-1)个,倒数第二层公有2^(H-2),顶点只有1(2^0)个,所以总共的时间复杂度为s = 1 * 2^(H-1) + 2 * 2^(H-2) + ... + (H-1) * 2^1 + H * 2^0 将H代入后s= 2N - 2 - log2(N),近似的时间复杂度就是O(N)。

⑻ 用一组{14,15,30,28,5,10}关键字序列,写出初始建堆过程图示,再根据初始堆写出堆排序过程图示。

起始序列为14,15,30,28,5,10,

(1)因此起始堆的情况如下:
14
15 30
28 5 10

(2)假设是打算得到一个从小到大的c,所以需要建大顶堆,起始状态从下向上建堆:
第一步: 第二步:
14 30
28 30 28 14
25 5 10 25 5 10

(3)此时已经建立完了初始的堆。此时堆顶元素30即为最大元素,将堆顶元素与堆最后
一个元素进行交换,此时30是最大元素位于队尾,因此无需继续排序。所以堆如下图
所示:10 28 14 25 5

(4)此时由于除被交换到堆顶的10以外其他的都基本有序,所以自上而下建堆得到的堆
如下:
28
25 14
10 5

(5)重复(3)和(4)步骤确定了28的位置并得到堆如下:
25
10 14
5

(6)重复(3)和(4)步骤确定了25的位置并得到堆如下:
14
10 5

(7)重复(3)和(4)步骤确定了14的位置并得到堆如下:
10
5

(8)重复(3)和(4)步骤确定了10的位置,此时只有一个数5也位于了堆的第一个位置,
因此排序完成。

(8)建堆的算法扩展阅读:

建堆效率

n个结点的堆,高度d =log2n。根为第0层,则第i层结点个数为2^i,考虑一个元素在堆中向下移动的距离。大约一半的结点深度为d-1,不移动(叶)。四分之一的结点深度为d-2,而它们至多能向下移动一层。树中每向上一层,结点的数目为前一层的一半,而子树高度加一。

这种算法时间代价为Ο(n)

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

Ο(log n)。

操作实现

在程序中,堆用于动态分配和释放程序所使用的对象。在以下情况中调用堆操作:

1.事先不知道程序所需对象的数量和大小。

2.对象太大,不适合使用堆栈分配器。

堆使用运行期间分配给代码和堆栈以外的部分内存。

传统上,操作系统和运行时库随附了堆实现。当进程开始时,操作系统创建称为进程堆的默认堆。如果没有使用其他堆,则使用进程堆分配块。

语言运行时库也可在一个进程内创建单独的堆。(例如,C 运行时库创建自己的堆。)除这些专用堆外,应用程序或许多加载的动态链接库 (DLL) 之一也可以创建并使用单独的堆。Win32 提供了一组丰富的API用于创建和使用专用堆。有关堆函数的优秀教程,请参阅 MSDN 平台 SDK 节点。

阅读全文

与建堆的算法相关的资料

热点内容
ug命令视频大全 浏览:610
箱子装货物最小容量编程 浏览:99
cad2014教程pdf 浏览:200
怎么遍历服务器同一类型的文件 浏览:437
惠普战66画图编程 浏览:806
java面向对象作业 浏览:570
cad插件制作加密狗 浏览:924
cmd命令对话框 浏览:291
安卓应用怎么常驻 浏览:677
安卓手机怎么群发小费才不会被锁 浏览:742
相机文件夹设置 浏览:856
centos7php怎么用 浏览:120
查看linux操作系统版本的命令 浏览:384
收支预算法怎么做 浏览:876
模板如何上传到服务器 浏览:373
如何同步安卓信息到新ipad 浏览:365
腾讯云轻量服务器流量警告 浏览:504
u盘备份linux 浏览:121
高压缩比活塞 浏览:93
压缩弹簧标准件 浏览:27