堆的操作——更改

631 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

更改操作

过程分析

首先我们给出函数的名字与参数。

void update(int x, int pos, int heap[])

pos为给定下标,x为要更改为的元素。

初始时的堆如下图所示。 image.png

此时heap[5]={6,1,3,2,5,7,4} 我们设pos=3,x=6。

替换后: image.png

可以观察到,6大于其子节点4,小根堆的定义不满足。所以,在覆盖值之后我们还需要比较pos位置的父节点与子节点的大小关系。

将位置调整后,结果如下:

image.png

代码实现

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;
		}
	
	} 
	
}