#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int h[1001];
int n;
void Swap(int x, int y) //交换h数组中下标为x和y的两个数
{
int tmp = h[x];
h[x] = h[y];
h[y] = tmp;
}
/*向下调整函数,以该结点向下调整
调整思路为: 判断该结点的左儿子,右儿子是否比它小,如果小就交换。
交换完之后,以交换的那个儿子结点,继续向下交换。直到没有比它小的儿子或该该点已经没有儿子。
*/
void shiftdown(int i) //传入一个需要向下调整的结点编号i
{
int t, flag = 0; //flag用来标记是否需要继续向下调整
while (i * 2 <= n && flag == 0)
{
//首先判断它和左儿子的关系,并用t记录值较小的节点编号
if (h[i] > h[i*2])
{
t = i*2;
}
else
{
t = i;
}
//如果它有右儿子,再对右儿子进行讨论
if (i*2 + 1 <= n)
{
//如果它的右儿子的值更小,更新较小的结点编号
if (h[t] > h[i*2 + 1])
t = i * 2 + 1;
}
//如果发现最小的编号不是自己,说明子结点中有比父节点更小的
if (t != i)
{
Swap(t, i);
i = t;
}
else
{
flag = 1;
}
}
}
void Creat()//建立最小堆
{
int i;
for(i = n/2 ; i >= 1; i--)//n为数组长度的一半,也就是树的深度
shiftdown(i);//
}
int deletmin() //返回堆顶元素
{
int t;
t = h[1];
h[1] = h[n];
h[n] = t;
n--;
shiftdown(1);
return t;
}
//创建函数,就是往数组中输入值之后,从最后一个非叶结点开始向下调整,一直到1号根结点
//删除最小值,就是将堆顶的元素与堆中最后一个元素交换,堆的大小减一,
//最后返回刚开始的那个堆顶元素。
int main()
{
int i, num,a,b;
scanf("%d", &num);//结点的总数
cout<<"输入的数字:"<<endl;
for(i = 1; i <= num; i++)
{
scanf("%d", &h[i]);
}
n = num;
Creat();
cout<<"建成之后的最小堆为"<<endl;
for(i = 1; i <= num; i++)
printf(" %d ", h[i]);//依次删除堆中最小值,并维护堆的性质
cout<<endl;
// cout<<"堆排之后:"<<endl;
//for(i = 1; i <= num; i++)
// printf(" %d ", deletmin());//依次删除堆中最小值,并维护堆的性质
//经过调整之后,发现数组h中数已经是有序的,不信可以输出出来看看哟(*^.^*)
cout<<endl;
cout<<"请输入你要插入的元素"<<endl;
scanf("%d",&a);
h[num+1]=a;
n = num+1;
Creat();
cout<<"建成之后的最小堆为"<<endl;
for(i = 1; i <= num+1; i++)
printf(" %d ", h[i]);//依次删除堆中最小值,并维护堆的性质
cout<<endl;
/*cout<<"堆排之后"<<endl;
for(i = 1; i <= num+1; i++)
printf(" %d ", deletmin());
cout<<endl;*/
cout<<"请输入需要删除的元素"<<endl;
scanf("%d",&b);
cout<<"删除之后的最小堆"<<endl;
for(i=1;i<=num+1;i++)
{
if(h[i]==b)
{
break;
}
}
h[i]=h[num+1];
n=num;
Creat();
for(i = 1; i <= num; i++)
printf(" %d ", h[i]);//依次删除堆中最小值,并维护堆的性质
return 0;
}
最小堆
最新推荐文章于 2021-12-04 10:23:30 发布