【数据结构·考研】堆的插入和删除

堆的建立 - 小根堆

堆的建立有两种方法:一是直接在原有数组上从最后一个非叶子结点开始不段执行向下筛选算法。二是给定一个空堆,把数组中的元素一个一个插入到堆里,每插入一个元素都进行向上筛选。

法一的时间复杂度 O ( N ),法二的时间复杂度 O ( N logN )。

小根堆的向下筛选算法

//小根堆的向下筛选算法 
void SiftDown(int* arr,int start,int m){
	int i = start;
	int j = 2*i + 1; //左孩子 
	int temp = arr[i]; 
	while(j <= m){
		if(j < m && arr[j] > arr[j+1]) j++; //选两孩子的小者 
		if(temp <= arr[j]) break; //根比小孩子小 
		else{ //双亲大向下滑动 
			arr[i] = arr[j];
			i = j; //小孩子的位置给根 
			j = 2*j + 1; //继续向下筛选 
		}
		arr[i] = temp; //找到自己目前合适的位置 
	}
} 

时间复杂度 O ( logN )。

堆的建立 - 方法一

//建初堆 
void CreateHeap(int* arr,int len){
	for(int i = len/2 - 1;i >= 0;i --)
		SiftDown(arr,i,len-1);
}

时间复杂度 O ( N )。

堆的插入 - 小根堆

小根堆的向上筛选算法

void SiftUp(int* arr,int start){ //从start开始,向上直到0,调整堆 
	int j = start;
	int i = (j - 1)/2; //i是j的双亲
	int temp = arr[j];
	while(j > 0){
		if(arr[i] <= temp) break;
		else{
			//双亲大向下落,继续向上检测 
			arr[j] = arr[i];
			j = i;
			i = (i - 1)/2;
		}
	}
	arr[j] = temp; 
}

时间复杂度 O ( logN )。

小根堆的插入

bool Insert(int* arr,int& len,int x){//堆、堆大小、插入元素
	if(len == HeapSize) return false; //堆满 
	arr[len] = x; //插在堆尾 
	SiftUp(arr,len); //向上调整
	len ++; 
	return true;
}

时间复杂度 O ( logN )。

堆的建立 - 方法二

void CreateHeap_2(int* arr,int* heap,int len){//数组、堆、数组长度
	int k = 0;
	for(int i = 0;i < len;i ++)
		Insert(heap,k,arr[i]); //一次插一个
}

时间复杂度 O ( N logN )。

堆的删除 - 小根堆

bool Remove(int* arr,int& len,int& x){//堆,堆大小,保存要删除的元素
	if(len == 0) return false;
	x = arr[0];
	arr[0] = arr[len - 1]; //把最后一个元素放到根
	len --; //大小-1
	SiftDown(arr,0,len-1); //调整
	return true; 
}

时间复杂度 O ( logN )。

完整代码:

#include<iostream>
using namespace std;
#define HeapSize 10 

//小根堆的向下筛选算法 
void SiftDown(int* arr,int start,int m){
	int i = start;
	int j = 2*i + 1; //左孩子 
	int temp = arr[i]; 
	while(j <= m){ 
		if(j < m && arr[j] > arr[j+1]) j++; //选两孩子的小者 
		if(temp <= arr[j]) break; //根比小孩子小 
		else{ //双亲大向下滑动 
			arr[i] = arr[j];
			i = j; //小孩子的位置给根 
			j = 2*j + 1; //继续向下筛选 
		}
		arr[i] = temp; //找到自己目前合适的位置 
	}
} 

//建初堆 
void CreateHeap_1(int* arr,int len){
	for(int i = len/2 - 1;i >= 0;i --)
		SiftDown(arr,i,len-1);
}

void SiftUp(int* arr,int start){ //从start开始,向上直到0,调整堆 
	int j = start;
	int i = (j - 1)/2; //i是j的双亲
	int temp = arr[j];
	while(j > 0){
		if(arr[i] <= temp) break;
		else{
			//双亲大向下落,继续向上检测 
			arr[j] = arr[i];
			j = i;
			i = (i - 1)/2;
		}
	}
	arr[j] = temp; 
}

bool Insert(int* arr,int& len,int x){
	if(len == HeapSize) return false; //堆满 
	arr[len] = x; //插在堆尾 
	SiftUp(arr,len); //向上调整
	len ++; 
	return true;
}

void CreateHeap_2(int* arr,int* heap,int len){
	int k = 0;
	for(int i = 0;i < len;i ++)
		Insert(heap,k,arr[i]);
}

bool Remove(int* arr,int& len,int& x){
	if(len == 0) return false;
	x = arr[0];
	arr[0] = arr[len - 1];
	len --;
	SiftDown(arr,0,len-1); //调整
	return true; 
}

int main(){
	cout<<"法一建堆:"<<endl; 
	int arr[] = {2,3,1,7,5,9,0,8,6,4};
	int len =10;
	for(int i = 0;i < len;i ++) cout<<arr[i]<<" ";
	cout<<endl;	
	CreateHeap_1(arr,10);
	for(int i = 0;i < len;i ++) cout<<arr[i]<<" ";
	cout<<endl;
	cout<<"Remove:"<<endl;	
	int x;
	cout<<Remove(arr,len,x)<<endl;
	for(int i = 0;i < len;i ++) cout<<arr[i]<<" ";
	cout<<endl;
	cout<<"Insert:"<<endl;
	cout<<Insert(arr,len,x)<<endl;
	for(int i = 0;i < len;i ++) cout<<arr[i]<<" ";
	cout<<endl;
	
	cout<<"法二建堆:"<<endl;
	int heap[HeapSize];
	int arr_2[] = {2,3,1,7,5,9,0,8,6,4};
	for(int i = 0;i < len;i ++) cout<<arr_2[i]<<" ";
	CreateHeap_2(arr_2,heap,len);
	cout<<endl;
	for(int i = 0;i < len;i ++) cout<<heap[i]<<" ";
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jiawen9

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值