数据结构之堆的简单实现

堆的存储结构实际上是一个完全二叉树,通过不断地调整各个节点的位置,可以得到最小堆或者最大堆,最小堆是每一个双亲都比每一个子节点的值要小,但是兄弟节点之间的大小未知,同样,最大堆即是双亲都比每一个子节点要小。对于堆来说,由于相对简便所以采用数组的方式来实现。从下标为 0 开始,如果双亲节点下标为 i ,则左子节点为 2* i + 1,右子节点下标为 2*i + 2。反过来,对于下表为 i 的子节点,其双亲下标为 (i - 1)/2,当然,有的地方是按从下标为 1 的位置开始存的,其实现都相同。
最大堆与最小堆实现完全相同只要改一下大于或小于号即可
首先建立结构体

typedef struct Heap{
	int *arr;//动态一维数组
	int size;//下标
	int capacity;//最大容量
}Heap;

接下来便是对堆初始化、插入、取最小元素的操作

//最小堆初始化 
void Init(Heap *heap,int max){
	if(max <= 0)
	return ; 
	heap = malloc(sizeof(int) *max);
	heap->size = 0;
	heap->capacity = max;
	
}

插入

//堆插入 
void Insert(Heap *heap, int x){
	//如果堆已满,则对堆的长度 + 5 
	if(heap->size == heap->capacity)
	{
		int *p = realloc(heap->arr,sizeof(int)*(heap->capacity + 5));
		heap->capacity = heap->capacity + 5;
		heap->arr = p;
	}
	
	heap->arr[heap->size++] = x;//堆的末尾添加元素 
	int i = heap->size - 1;//数组对应最大下标 
	while(i != 0){
		int j = (i - 1)/2;// j 为双亲 
		if(x >= heap->arr[j])
		break;
		heap->arr[i] = heap->arr[j];//交换双亲与子节点 
		i = j; //重复以上操作 
	}
	heap->arr[i] = x;//把 x 插到合适的位置 
}

移除最小元素

int dele(Heap *heap){
	if(heap->size == 0)
	return;
	
	int temp = heap->arr[0];//如果就一个节点则直接返回即可 
	heap->size--;
	if(heap->size == 0)
	return temp;
	
	int i = 0;//双亲,刚开始指向 0 位置 
	int j = 2*i+1; //左子节点 
	int x = heap->arr[heap->size];//待调整的尾部元素 
	while(j <= heap->size -1){
		if(j < heap->size-1 && heap->arr[j] > heap->arr[j+1])//左子节点比右子节点大则 j 指向右节点 
		j++;
		
		if( x <= heap->arr[j])//如果 x 小于了子节点则不用再调整 
		break;
		
		heap->arr[i] = heap->arr[j]; //交换子节点与双亲 
		i = j;	//重复以上操作 
		j = 2*i + 1;
	}
	heap->arr[i] = x;//把尾部元素插到合适的位置 
	return temp;
	
}

以上是最小堆的操作,下面附上完整代码(包含最小堆与最大堆)

#include <stdio.h>
#include <stdlib.h>

typedef struct Heap{
	int *arr;
	int size;
	int capacity;
}Heap;

//最小堆初始化 
void Init(Heap *heap,int max){
	if(max <= 0)
	return ; 
	heap = malloc(sizeof(int) *max);
	heap->size = 0;
	heap->capacity = max;
	
}

//堆插入 
void Insert(Heap *heap, int x){
	//如果堆已满,则对堆的长度 + 5 
	if(heap->size == heap->capacity)
	{
		int *p = realloc(heap->arr,sizeof(int)*(heap->capacity + 5));
		heap->capacity = heap->capacity + 5;
		heap->arr = p;
	}
	
	heap->arr[heap->size++] = x;//堆的末尾添加元素 
	int i = heap->size - 1;//数组对应最大下标 
	while(i != 0){
		int j = (i - 1)/2;// j 为双亲 
		if(x >= heap->arr[j])
		break;
		heap->arr[i] = heap->arr[j];//交换双亲与子节点 
		i = j; //重复以上操作 
	}
	heap->arr[i] = x;//把 x 插到合适的位置 
}

//移除堆的最小元素,也即是根节点 
int dele(Heap *heap){
	if(heap->size == 0)
	return;
	
	int temp = heap->arr[0];//如果就一个节点则直接返回即可 
	heap->size--;
	if(heap->size == 0)
	return temp;
	
	int i = 0;//双亲,刚开始指向 0 位置 
	int j = 2*i+1; //左子节点 
	int x = heap->arr[heap->size];//待调整的尾部元素 
	while(j <= heap->size -1){
		if(j < heap->size-1 && heap->arr[j] > heap->arr[j+1])//左子节点比右子节点大则 j 指向右节点 
		j++;
		
		if( x <= heap->arr[j])//如果 x 小于了子节点则不用再调整 
		break;
		
		heap->arr[i] = heap->arr[j]; //交换子节点与双亲 
		i = j;	//重复以上操作 
		j = 2*i + 1;
	}
	heap->arr[i] = x;//把尾部元素插到合适的位置 
	return temp;
	
}

int isEmpty(Heap *heap){
	if(heap->size == 0)
	return 1;
	return 0;
	
}

//以下为最大堆

void InitMax(Heap *heap, int max){
	if(max <= 0)
	return ; 
	heap = malloc(sizeof(int) *max);
	heap->size = 0;
	heap->capacity = max;

}

void InsertMax(Heap *heap, int x){
	if(heap->size == heap->capacity){
		int *p = realloc(heap->arr,sizeof(int)*(heap->capacity + 5));
		heap->arr = p;
		heap->capacity = heap->capacity + 5;
	}
	heap->arr[heap->size++] = x;
	int i = heap->size - 1;
	while(i != 0){
		int j = (i - 1)/2;
		if(x <= heap->arr[j])
		break;
		heap->arr[i] = heap->arr[j];
		i = j;
	}
	heap->arr[i] = x;
} 

int deleMax(Heap *heap){
	if(heap->size == 0)
	return ;
	int temp = heap->arr[0];
	heap->size--;
	if(heap->size == 0)
	return temp; 
	
	int x = heap->arr[heap->size];
	int i = 0;
	int j = 2*i + 1;
	while(j <= heap->size - 1){
		if(j < heap->size - 1 && heap->arr[j] < heap->arr[j+1])
		j++;
		if(heap->arr[j] <= x)
		break;
		heap->arr[i] = heap->arr[j];
		i = j;
		j = 2*i + 1;
	}
	heap->arr[i] = x;
	return temp;
}

int main(){
	Heap *heap;
	Init(heap,5);
	int a[8] = {5,6,8,2,1,3,9,7};
	int i;
	for(i = 0; i < 8; i++){
		Insert(heap,a[i]);
	}
	
	while(!isEmpty(heap)){
		printf("%d ",dele(heap));
	}
	
//	int i;
//	int a[8] = {5,6,8,2,1,3,9,7};
//	Heap *heap2;
//	InitMax(heap2,5);
//	for(i = 0; i < 8; i++){
//		InsertMax(heap2,a[i]);
//	}
//	
//	while(!isEmpty(heap2)){
//		printf("%d ",deleMax(heap2));
//	}
}

注意:最小堆与最大堆的测试请分开测试

猜你喜欢

转载自blog.csdn.net/qq_43060759/article/details/83277732