您的位置:首页 > 其它

堆的建立、删除、插入操作以及堆排序

2013-10-29 15:56 381 查看
二叉堆是一种特殊的堆,二叉堆是完全二元树或者是近似完全二元树。
二叉堆有两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

堆一般用数组存放:跟节点为0节点,i节点的左子节点为2*i+1,右子节点为2*i+2;



堆的操作: 建立、插入、删除



插入:因为从根节点到叶节点是一个有序序列。将新插入的节点放到最后然后将其放到这个有序序列。
删除:删除某一个节点, 将最后一个节点填充到删除的节点处,然后将此节点看做成根节点构造一个堆。
堆的排序:因为堆的根节点是最小堆值,所以每次取根节点,然后将其删除,剩余的节点重新构造成堆以此递归完成排序。
使用最小堆得到递增序列,最大堆得到递减序列。
由于每次重新恢复堆的时间复杂度为O(logN),共N - 1次重新恢复堆操作,再加上前面建立堆时N / 2次向下调整,每次调整时间复杂度也为O(logN)。二次操作时间相加还是O(N * logN)。故堆排序的时间复杂度为O(N * logN)。下面为代码以最小堆为例:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;
#define N 1000

int array
;

int adjustHeap(int *a, int i, int n)
{
int j , temp;

temp = a[i];
j =  2*i + 1;
if(j < n)
{
if((j+1 < n) && (a[j+1] <= a[j]))
{
j++;
}
if(a[j] < temp)
{
a[i] = a[j];
a[j] = temp;
adjustHeap(a, j, n);
}
}
return 1;
}

//建立最小堆
int buildHeap(int *a, int n)
{
for(int i = n/2 - 1; i >= 0; i--)
adjustHeap(a, i, n);
return 1;
}

//删除节点i
int delHeap(int *a, int i, int n)
{
if(i < n)
{
swap(a[i], a[n-1]);
adjustHeap(a, i, n-1);
}
return 1;
}

//插入节点n
int insertHeap(int *a, int n)
{
if(n == 0)
return 1;

int j = n/2 -1;
if(a
>= a[j])
return 1;
swap(a
, a[j]);
insertHeap(a, j);
return 1;
}

int sortHeap(int *a, int n)
{
int i = n;

while(i >=0 )
{
delHeap(a, 0, i);
i--;
}
return 1;
}
int main(int argc, char *argv[])
{
int a
;
int num, i;

printf("请输入节点数量: ");
scanf("%d", &num);
printf("\n请输入%d个节点 以空格结束!\n", num);
for(i = 0; i < num; i++)
{
scanf("%d", &a[i]);
}

buildHeap(a, num);
printf("建成的堆:\n");
for(i = 0; i < num; i++)
{
printf("%d ", a[i]);
}
printf("\n");

delHeap(a, 6, num);
printf("删除后的堆:\n");
for(i = 0; i < num -1; i++)
{
printf("%d ", a[i]);
}
printf("\n");

a[num -1] = 14;
insertHeap(a, num-1);
printf("插入数据后的堆:\n");
for(i = 0; i < num; i++)
{
printf("%d ", a[i]);
}
printf("\n");

sortHeap(a, num);
printf("排序后的数据:\n");
for(i = 0; i < num; i++)
{
printf("%d ", a[i]);
}
printf("\n");

return 1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: