数据结构——堆,C语言实现

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>

typedef struct Heap {
	int arr[30];
	int size;
}	Heap;

void HeapInit(Heap *Hp, int arr[], int size)
{
	assert(Hp);
	memset(Hp->arr, 0, sizeof(int)*size);
	memcpy(Hp->arr, arr, sizeof(int)*size);
	Hp->size = size;
}

void Swap(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void AdjustDown(Heap *Hp, int parent)
{
	int left = parent*2 + 1;
	int right = parent*2 + 2;
	int maxChild;

	if(left > Hp->size) {
		return;
	}

	//找出大孩子
	maxChild = left;
	if(right < Hp->size && Hp->arr[left] < Hp->arr[right]) {
		maxChild = right;
	}

	//判断大孩子和双亲的大小关系
	if(Hp->arr[parent] < Hp->arr[maxChild])
		Swap(&Hp->arr[parent], &Hp->arr[maxChild]);

	AdjustDown(Hp, maxChild);
}

void AdjustUp(Heap *Hp, int child)
{
	//有问题,为什么把while换成递归就会出错
	int parent = (child - 1)/2;

	while(1) {
		parent = (child - 1)/2;
		//已经调整到根了
		if(child == 0) {
			break;
		}

		//已经调整到满足堆了
		if(Hp->arr[parent] > Hp->arr[child]) {
			break;
		}

		//走到这里表示孩子比双亲大,需要调整
		Swap(Hp->arr + parent, Hp->arr + child);

		//调整完成之后需要调整下一个结点
		child = parent;
	}
}

void HeapCreat(Heap *Hp, int size)
{
	assert(Hp);
	if(size <= 1) {
		return;
	}

	int i;
	for(i = (size - 1 - 1)/2 ; i >= 0 ; i--) {
		AdjustDown(Hp, i);
	}
}

void HeapInsert(Heap *Hp, int data)
{
	assert(Hp);
	//插入只能在最后一个结点后面插
	//但是插入之后不满足堆,需要重新调整
	Hp->arr[Hp->size++] = data;
	AdjustUp(Hp, Hp->size-1);
}

void HeapDelTop(Heap *Hp)
{
	assert(Hp);
	Swap(&Hp->arr[0], &Hp->arr[Hp->size - 1]);
	Hp->size--;
	int i;
	for(i = Hp->size - 1 ; i >= 0 ; i--) {
		AdjustDown(Hp, i);
	}
}

AdjustDownArray(int arr[], int size, int parent)
{
	int left = parent * 2 + 1;
	int right = parent * 2 + 2;
	int max;
	while(1) {
		left = parent * 2 + 1;
		right = parent * 2 + 2;
		if(left > size) {
			break;
		}
	
		max = left;
		if(right < size && arr[left] < arr[right]) {
			max = right;
		}
		if(arr[parent] < arr[max]) {
			Swap(arr + parent, arr + max);
		}
		//AdjustDownArray(arr, size, max);
		parent = max;
	}
}

//在数组中找到最小的k个数
void TopK(int arr[], int size, int k)
{
	int *TopArr = (int *)malloc(sizeof(int)*k);
	int i = 0;
	for(i = 0 ; i < k ; i++) {
		TopArr[i] = arr[i];
	}
	
	for(i = (k - 2)/2 ; k >= 0 ; i--) {
		AdjustDownArray(TopArr, k, i);
	}

	for(i = k ; i < size ; i++) {
		if(arr[i] > TopArr[0])
			AdjustDownArray(TopArr, k, 0);
	}
	
	for (i = 0 ; i < k ; i++) {
		printf("%d  ",TopArr[i]);
	}
}

void HeapPrint(Heap *Hp)
{
	assert(Hp);
	int i = 0;
	for(i = 0 ; i < Hp->size ; i++) {
		printf("%d  " , Hp->arr[i]) ;
	}
	printf("\n");
}

void HeapPop(Heap *Hp)
{
	assert(Hp);
	if(Hp->size < 1) {
		return;
	}
	Hp->arr[0] = Hp->arr[1];
	Hp->size--;
	AdjustDown(Hp, 0);
}

int main()
{
	int arr[] = {21, 45, 34, 18, 64, 75, 59, 33};
	Heap Hp;
	HeapInit(&Hp, arr, sizeof(arr)/sizeof(int));
	HeapCreat(&Hp, sizeof(arr)/sizeof(int));
	HeapPrint(&Hp);

	HeapInsert(&Hp, 44);
	HeapPrint(&Hp);

	HeapDelTop(&Hp);
	HeapPrint(&Hp);

	//TopK(arr, sizeof(arr)/sizeof(int), 3);
	HeapPop(&Hp);
	HeapPrint(&Hp);

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值