小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
更改操作
过程分析
首先我们给出函数的名字与参数。
void update(int x, int pos, int heap[])
pos为给定下标,x为要更改为的元素。
初始时的堆如下图所示。
此时heap[5]={6,1,3,2,5,7,4} 我们设pos=3,x=6。
替换后:
可以观察到,6大于其子节点4,小根堆的定义不满足。所以,在覆盖值之后我们还需要比较pos位置的父节点与子节点的大小关系。
将位置调整后,结果如下:
代码实现
1.更改pos出的值
heap[pos]=x;
其中heap的长度没有改变。
2.判断父子结点大小
如果小于父节点就上飘
if(heap[i]<heap[i/2]){
temp=heap[i];
heap[i]=heap[i/2];
heap[i/2]=temp;
i=i/2;
}
如果大于左子节点且左子节点最小或者右子结点不存在时,向左子节点下沉
else if( (heap[i]>heap[2*i]&&heap[2*i]<heap[2*i+1]) || 2*i+1>len ){//如果大于子节点就下沉
temp=heap[i];
heap[i]=heap[2*i];
heap[2*i]=temp;
i=2*i;
如果大于右子结点,且右子结点小于左子节点时,向右子结点下沉
else if(heap[i]>heap[2*i+1]&&heap[2*i+1]<heap[2*i]){
temp=heap[i];
heap[i]=heap[2*i+1];
heap[2*i+1]=temp;
i=2*i+1;
}
函数代码
//更新pos处的元素为x
void update(int x, int pos, int heap[]){
heap[pos]=x;
int i=pos;
while(1){
//循环退出条件
if(i<=1||2*i>len){
break;
}
int temp;
//如果小于父节点就上飘
if(heap[i]<heap[i/2]){
temp=heap[i];
heap[i]=heap[i/2];
heap[i/2]=temp;
i=i/2;
}else if( (heap[i]>heap[2*i]&&heap[2*i]<heap[2*i+1]) || 2*i+1>len ){//如果大于子节点就下沉
temp=heap[i];
heap[i]=heap[2*i];
heap[2*i]=temp;
i=2*i;
}else if(heap[i]>heap[2*i+1]&&heap[2*i+1]<heap[2*i]){
temp=heap[i];
heap[i]=heap[2*i+1];
heap[2*i+1]=temp;
i=2*i+1;
}
}
}