堆:Heap是计算机科学中一类特殊的数据结构的统称,通常是一个可以被看做一棵完全二叉树的数组对象。堆是非线性数据结构,相当于一给2一维数组,有两个直接后继。
堆的性质:堆中某个节点的值总是不大于或不小于其父节点的值,且总是一棵完全二叉树。
堆的分类:大根堆、小根堆
大根堆:将根节点最大的堆叫做最大堆或大根堆,及根节点的元素值最大,且所有父节点的值大于其左右子节点的值
小根堆:将根节点最小的堆叫做最小堆或小根堆,及根节点的元素值最小,且所有父节点的值小于其左右子节点的值
堆的定义如下: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个元素的最小值(或最大值)
以最大堆为例进行堆操作分析:
一:堆的上移动操作:如果修改堆中某个元素,使得它的值大于父节点的值,导致破坏了最大堆的性质,因此需要对该元素实现上移操作。上移一次后需要再次判断是否大于其父节点的值,直到上移至根节点为止
void sift_up(int *H,int i)
{
while(i!=1)
{
if(H[i]>H[i/2])
swap(H[i],H[i/2]);
i=i/2;
}
}二:堆的下移操作:如果修改堆中某个元素,使得它的值小于其子节点值,导致破坏了最大堆的性质,,因此需要对该元素实现下移操作。 下移一次后需要再次判断是否小于其子节点的值,直到下移至叶节点为止
void sift_down(int *H,int m,int i)
{
while((i=2*i)<=m) //判断该结点是否为叶子节点
{
if(i+1<=m && H[i+1]>H[i]) //选取下移节点的左右子节点中较大的
i++;
if(H[i]>H[i/2]) //i/2即为我们需要下移的元素,如果比子节点中最大元素小,进行交换
swap(H[i],H[i/2]);
}
}三:堆的删除操作:如果我们删除下标为 i 的元素,可以用堆中最后1个元素替代i,然后对这个元素执行上移或者下移操作
void heap_delete(int *H,int i ,int &m)
{
if(i>m)
return;
else
{
int a,b;
a=H[i];
b=H[m];
H[i]=b;
m--;
if(a>b)
{
sift_down(H,m,i);
}
else
{
sift_up(H,i);
}
}
}四:堆的插入操作:插入一个元素时,插入到堆最后1个元素后面,然后对该元素执行上移操作
void Insert(int *H,int &m,int num)
{
m++;
H[m]=num;
sift_up(H,m);
}五:堆的建立:以数组arr为对象建立堆数组hrr,g为arr数组元素个数,m为堆的元素个数该参数通过插入等操作带出,从Hrr[1]开始存储元素
void make_heap(int *arr,int *hrr,int g,int &m)
{
m=0;
for(int i=0;i{
Insert(hrr,m,arr[i]);
}
}六:堆的排序:假设堆有n个元素,由于堆的第一个元素一定是最大的元素,因此可以让第一个元素和第n个元素互换,然后对第一个元素执行下操作。接着,对n-1个元素执行相同的操作,让第一个元素与第n-1个元素互换,然后对第一个元素执行下移操作,依次类推,最后的堆就是从小到大排序好的堆。
void heap_sort(int *H,int m)
{
int i;
for(i=m;i>0;i--)
{
swap(H[i],H[1]);
sift_down(H,i-1,1);
}
}
以最大堆为例堆排序:
void HeapAdjust(int arr[], int pos, int len)//以堆的形式调整数组元素的位置
{
int i = pos;
int j = 2 * i + 1;
int tmp = 0;
for (j; j < len; j = 2 * i + 1)
{
if (j < len - 1 && arr[j + 1] > arr[j])++j;
if (arr[i] >= arr[j])break;
swap(arr[i],arr[j])
i = j;
}
}
void HeapSort(int arr[], int len)
{
int tmp = 0;
for (int i = len / 2 - 1; i >= 0; --i)
{
HeapAdjust(arr, i, len);
}
for (int i = len - 1; i > 0; --i)
{
swap(arr[0],arr[i]);
HeapAdjust(arr, 0, i);
}
}