堆的模拟实现

堆的模拟实现

//heap.p文件
#pragma  once 
#include <stdlib.h>
#include <memory.h>

typedef int HPDataType;

typedef struct Heap{
	HPDataType* _array;
	int _size;
	int _capacity;

}Heap;

void Swap(int array[], int left, int right);
void shiftCreat(Heap* hp, HPDataType* array, int size);

void shiftDownLittle(HPDataType* array, int size, int parent);
void shiftUpLittle(HPDataType* array, int child);


void shiftDownBig(HPDataType* array, int size, int parent);
void shiftUpBig(HPDataType* array, int child);
//尾插
void heapPush(Heap* hp, HPDataType data);
// 删除堆顶元素
void heapPop(Heap* hp);

HPDataType heapTop(Heap* hp);
HPDataType heapEmpty(Heap* hp);

void heapPrint(Heap* hp);
//heap.c文件
#include "heap.h"
#include <stdlib.h>
#include <stdio.h>
//建堆
//用一个数组的数据创建一个堆,  从最后一个非叶子节点开始(最后一个非叶子的节点: (数组大小-2) / 2 ),进行向下调整,直到调整到根节点的位置,结束.
void shiftCreat(Heap* hp, HPDataType* array, int size) {
	hp->_array = (HPDataType*)malloc(sizeof(HPDataType)*size);
	memcpy(hp->_array, array, sizeof(HPDataType)*size);
	hp->_size = size;
	hp->_capacity = size;
	//建堆 ,从最后一个非叶子节点开始建堆  parent =(size-2)/2
	for (int parent = (size - 2) / 2; parent >= 0; parent--) {
		shiftDownBig(hp->_array, size, parent);
	}
}

void Swap(int array[], int left, int right) {
	int temp = array[left];
	array[left] = array[right];
	array[right] = temp;
}
//小堆的向下调整 parent: 起始调整的位置
void shiftDownLittle(HPDataType* array, int size, int parent) {
	//左孩子位置
	int child = 2 * parent + 1;
	while (child < size) {
		//从左右孩子中选一个最小的
		//建小堆
		if (child + 1 < size && array[child + 1] < array[child])
			++child;
		//在去和父节点比较
		if (array[child] < array[parent]) {
			Swap(array, child, parent);
			// 更新
			parent = child;
			child = 2 * parent + 1; //仍然是左孩子的位置
		}
		else
			break;
	}
}
//大堆的向下调整 parent: 起始调整的位置
void shiftDownBig(HPDataType* array, int size, int parent) {
	//左孩子位置
	int child = 2 * parent + 1;
	while (child < size) {
		//从左右孩子中选一个最小的
		//建小堆
		if (child + 1 < size && array[child + 1] > array[child])
			++child;
		//在去和父节点比较
		if (array[child] > array[parent]) {
			Swap(array, child, parent);
			// 更新
			parent = child;
			child = 2 * parent + 1; //仍然是左孩子的位置
		}
		else
			break;
	}
}
//堆的插入: 插入之后仍然满足是一个新的堆
//步骤: 1. 先把元素放在数组最后的一个位置,然后在进行向上调整
void heapPush(Heap* hp, HPDataType data) {
	//检查容量
	if (hp->_size == hp->_capacity) {
		hp->_capacity *= 2;
		hp->_array = (HPDataType*)realloc(hp->_array, sizeof(HPDataType)*hp->_capacity);
	}

	//尾插
	hp->_array[hp->_size++] = data;
	shiftUpBig(hp->_array, hp->_size - 1);

}
//删除堆顶元素  (最值)
//步骤: 1.先交换顶部和尾部的元素 2.删除最后一个元素 3. 进行一次 s向下调整
void heapPop(Heap* hp) {
	if (hp->_size > 0) {
		//1.交换堆顶和最后一个椰子
		Swap(hp->_array, 0, hp->_size - 1);
		//2.删除最后一个元素
		hp->_size--;
		//3.向下进行调整
		shiftDownBig(hp->_array, hp->_size, 0);

	}
}

//向上调整  堆插入的时候需要向上调整
void shiftUpLittle(HPDataType* array, int child) {
	int parent = (child - 1) / 2;
	while (child > 0) {
		if (array[child] < array[parent]) {

			Swap(array, child, parent);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}
//向上调整  堆插入的时候需要向上调整
void shiftUpBig(HPDataType* array, int child) {
	int parent = (child - 1) / 2;
	while (child > 0) {
		if (array[child] > array[parent]) {

			Swap(array, child, parent);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}

HPDataType heapTop(Heap* hp) {
	return hp->_array[0];

}
HPDataType heapEmpty(Heap* hp) {
	if (hp->_size == 0) {
		return 1;
	}
	else {
		return 0;
	}

}


void heapPrint(Heap* hp) {
	for (int i = 0; i < hp->_size; i++) {
		printf("%d ", hp->_array[i]);
	}
	printf("\n");

}
//test.c文件
#include "heap.h"
#include <stdio.h>
#include <stdlib.h>

void test() {
	//大堆数组
	int array[11] = { 100, 50, 30, 20, 25, 18, 10, 5, 15, 21, 23 };
	Heap hp;
	shiftCreat(&hp, array, 11);

	heapPrint(&hp);
}

void test2() {
	int array[10] = { 30, 45, 15, 35, 36, 18, 53, 72, 48, 93 };
	Heap hp;
	shiftCreat(&hp, array, 10);
	heapPrint(&hp);
	printf("heapPush: \n");
	heapPush(&hp, 80);
	heapPrint(&hp);
	printf("heapPop: \n");

	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
}
void test3() {

	int array[10] = { 30, 45, 15, 35, 36, 18, 53, 72, 48, 93 };
	Heap hp;
	shiftCreat(&hp, array, 10);
	heapPrint(&hp);
	printf("heapPush: \n");
	heapPush(&hp, 80);
	heapPrint(&hp);
	printf("heapPop: \n");

	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
	heapPush(&hp, 8);
	heapPrint(&hp);

	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
	heapPush(&hp, 100);
	heapPrint(&hp);

	heapPop(&hp);
	heapPrint(&hp);
	heapPop(&hp);
	heapPrint(&hp);
}

void test4() {
	int array[10] = { 30, 45, 15, 35, 36, 18, 53, 72, 48, 93 };
	Heap hp;
	shiftCreat(&hp, array, 10);
	heapPrint(&hp);
	while (heapEmpty(&hp) != 1) {
		printf("%d\n",heapTop(&hp));
		heapPop(&hp);
	}
}

int main () {
	//test();
	//test2();
	//test3();
	test4();
	system("color A");
    system ("pause");
    return 0;
}

堆排序的实现

//sort.h文件
#pragma once 

typedef struct Heap{
	int* _array;
	int _capacity;
	int _size;

}Heap;
void heapSort(int* array, int n);
void shiftDownBig(int* array, int n, int i);
void Swap(int* array, int left, int right);

//sort.c文件

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

void heapSort(int* array, int n) {
	//建堆
	for (int i = (n - 2) / 2; i >= 0; i--) {
		// 建大堆  
		shiftDownBig(array, n, i);
	}
	//循环尾删
	int size = n;
	while (size > 0) {
		//交换
		Swap(array, 0, size - 1);
		//删除
		--size;
		shiftDownBig(array, size, 0);
	}
}

void Swap(int* array, int left, int right) {
	int temp = array[left];
	array[left] = array[right];
	array[right] = temp;
}

void shiftDownBig(int* array, int size, int parent) {
	int child = 2 * parent + 1;
	while (child < size) {
		while (child + 1 < size && array[child + 1] > array[child])
			child++;
		if (array[child] > array[parent]) {
			Swap(array, child, parent);
			parent = child;
			child = 2 * parent + 1;
		}
		else {
			break;
		}
	}
}

//test.c文件

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

void test2() {
	int array[10] = { 30, 45, 15, 35, 36, 18, 53, 72, 48, 92 };
	heapSort(array, 10);
	for (int i = 0; i < 10;i++) {
		printf("%d ",array[i]);
	}
	printf("\n");
}

int main () {

	test2();
    system("color A");
    system ("pause");
    return 0;
}
总结
堆的操作:

1.插入: 尾插+向上调整
2.删除: 交换+尾删+向下调整
3.堆顶元素array[0]

应用场景: topK
找最小K:建大堆
找最大K:建小堆

堆排序: 建堆 + 循环尾删

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值