堆的描述
堆是对基于数组的树的重要应用场合之一。它是节点间具有层次次序关系的完全二叉树。其中,父节点值大于或等于其孩子节点值的,叫“最大堆(maximum heap)”;父节点值小于或等于孩子节点值的,叫“最小堆(minimum heap)”.在最大堆中,根中的元素值最大;在最小堆中,根中的元素值最小。本节将研究最大堆 。
堆的存储特点
在这里,我们研究作为 顺序表存储的堆。它是按某种次序将一系列数据以完全二叉树形式存放的一种表。它要求堆中的节点的值都大于或等于其孩子节点的值。
按照这种存储方式,可知第i个元素的左右儿子分别是第2i和第2i+1个元素,而它的父亲节点是第i/2个元素。由于父亲节点和儿子节点具有这样的顺序关系,所以可以方便地由父亲节点找到儿子节点,反之亦然。
可见,这种存储方式大大节省了存储空间,高效快速。
堆的描述
堆是对基于数组的树的重要应用场合之一。它是节点间具有层次次序关系的完全二叉树。其中,父节点值大于或等于其孩子节点值的,叫“最大堆(maximum heap)”;父节点值小于或等于孩子节点值的,叫“最小堆(minimum heap)”.在最大堆中,根中的元素值最大;在最小堆中,根中的元素值最小。本节将研究最大堆 。
堆的存储特点
在这里,我们研究作为 顺序表存储的堆。它是按某种次序将一系列数据以完全二叉树形式存放的一种表。它要求堆中的节点的值都大于或等于其孩子节点的值。
按照这种存储方式,可知第i个元素的左右儿子分别是第2i和第2i+1个元素,而它的父亲节点是第i/2个元素。由于父亲节点和儿子节点具有这样的顺序关系,所以可以方便地由父亲节点找到儿子节点,反之亦然。
可见,这种存储方式大大节省了存储空间,高效快速。
堆的相关操作
作为抽象表结构,堆允许增加和删除表项。插入过程不用假定新表项占有一个特定的位置而只需维持堆顺序。但是删除操作总是删去表中的最大项 (根)。
堆可以用于那些客户程序想直接访问最大(小)元素的场合。作为表,堆并不提供Find操作,而对表的直接访问是只读的。所有的堆处理算法都有责任更新树和维持堆顺序。
1.建堆:数组具有对应的树表示形式。一般情况下,树并不满足堆的条件。通过重新排列元素,可以建立一棵“堆化”的树。
2.插入一个元素:新元素被加入到表中,随后树被更新以恢复堆次序。例如,下面的步骤将15加入到表中。
3.删除一个元素:删除总是发生在根节点处。用表中的最后一个元素来填补空缺位置,结果树被更新以恢复堆条件。
在堆实现时我们是采用数组来存储堆的完全二叉树表示,并且用一种有效的算法来保证对堆的所有操作不破坏堆的性质。这种表示的主要问题在于数组的大小需要事先确定,这使得对堆的大小有了一个初始的限定。在堆中数据增长到超过这个界限时虽然可以通过复制的方法建立更大的向量来存放堆,但整个向量的复制是不可避免的,这大大降低了操作效率。为避免这个问题,可把二叉树的顺序存储改为二叉树的链表存储,这就要用到斜堆(skewheap) .
依照题意,采用Shell排序法排序的各趟的结果如下:
初始:10,18,4,3,6,12,1,9,15,8
1趟: 10,1,4,3,6,12,18,9,15,8
2趟: 4,1,6,3,10,8,15,9,18,12
3趟: 1,3,4,6,8,9,10,12,15,18
第三趟无元素交换,则排序结束。
算法Bubble 的C++描述
void Bubble ( Element *R,int n ) // 排序记录R1,R2,…,Rn
{ int bound,j,t;
Element e;
bound = n;
while ( ! bound )
{t = 0;
for ( j = 1;j<bound;j++ )
if ( R[j]. GetKey( ) > R[j+1]. GetKey( ) )
{e = R[j];R[j] = R[j+1];R[j+1] = e;
t = j;}
bound = t;
}
}