数据结构——堆

#pragma once

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

typedef struct Heap {
	int	array[100];
	int	size;
}	Heap;

void HeapInit(Heap *pH, int array[], int size)
{
	assert(pH);
	memcpy(pH->array, array, sizeof(int)* size);
	pH->size = size;
}

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

// 建大堆
void AdjustDownRecursion(Heap *pH, int parent)
{
	// 判断是否是叶子结点
	// 没有左孩子,没有右孩子
	// 完全二叉树,没有左孩子,一定没有右孩子
	// 有没有左孩子,判断左孩子的下标是否越界
	int left = 2 * parent + 1;
	int right = 2 * parent + 2;
	int maxChild;

	if (left >= pH->size) {
		// 是叶子结点
		return;
	}

	// 肯定有左孩子,右孩子可能有,可能没有
	// 找出谁是大的孩子
	maxChild = left;
	if (right < pH->size && pH->array[right] > pH->array[left]) {
		maxChild = right;
	}

	if (pH->array[parent] > pH->array[maxChild]) {
		// 现在满足堆了
		return;
	}

	Swap(pH->array + parent, &(pH->array[maxChild]));

	AdjustDownRecursion(pH, maxChild);
}


// 建大堆
void AdjustDownLoop(Heap *pH, int parent)
{
	while (1) {
		// 判断是否是叶子结点
		// 没有左孩子,没有右孩子
		// 完全二叉树,没有左孩子,一定没有右孩子
		// 有没有左孩子,判断左孩子的下标是否越界
		int left = 2 * parent + 1;
		int right = 2 * parent + 2;
		int maxChild;

		if (left >= pH->size) {
			// 是叶子结点
			return;
		}

		// 肯定有左孩子,右孩子可能有,可能没有
		// 找出谁是大的孩子
		maxChild = left;
		if (right < pH->size && pH->array[right] > pH->array[left]) {
			maxChild = right;
		}

		if (pH->array[parent] > pH->array[maxChild]) {
			// 现在满足堆了
			return;
		}

		Swap(pH->array + parent, &(pH->array[maxChild]));

		parent = maxChild;
		//AdjustDownRecursion(pH, maxChild);
	}
}

void HeapMake(Heap *pH)
{
	int i;
	for (i = (pH->size - 2) / 2; i >= 0; i--) {
		AdjustDownLoop(pH, i);
	}
}

int HeapTop(Heap *pH)
{
	return pH->array[0];
}

int HeapSize(Heap *pH)
{
	return pH->size;
}

int HeapIsEmpty(Heap *pH)
{
	return pH->size == 0 ? 1 : 0;
}

void HeapPop(Heap *pH)
{
	assert(pH);
	assert(pH->size > 0);
	pH->array[0] = pH->array[pH->size - 1];
	pH->size--;
	AdjustDownLoop(pH, 0);
}

void AdjustUp(Heap *pH, int child)
{
	int parent;
	while (1) {
		// (0 - 1) / 2 = 0
		parent = (child - 1) / 2;

		if (child == 0) {
			// 走到整棵树的根了
			break;
		}

		if (pH->array[parent] >= pH->array[child]) {
			// 满足堆了
			break;
		}

		Swap(pH->array + parent, pH->array + child);
		child = parent;
	}
}

void HeapInsert(Heap *pH, int data)
{
	pH->array[pH->size++] = data;
	AdjustUp(pH, pH->size - 1);
}


// 大堆
void AdjustDownArray(int array[], int size, int root)
{
	int parent = root;
	int left, right, max;
	while (1) {
		left = parent * 2 + 1;
		right = parent * 2 + 2;
		if (left >= size) {
			return;
		}

		max = left;
		if (right < size && array[right] > array[left]) {
			max = right;
		}

		if (array[parent] >= array[max]) {
			return;
		}

		Swap(array + parent, array + max);
		parent = max;
	}
}

// 在 array 中找到最小的 k 个数
int * TopK(int array[], int size, int k)
{
	int i;
	int *rarray = (int *)malloc(sizeof(int)* k);
	for (i = 0; i < k; i++) {
		rarray[i] = array[i];
	}

	// 建堆 (rarray)
	for (i = (k - 2) / 2; i >= 0; i--) {
		AdjustDownArray(rarray, k, i);
	}

	for (i = k; i < size; i++) {
		if (array[i] < rarray[0]) {
			rarray[0] = array[i];
			// 对 rarray 进行向下调整
			AdjustDownArray(rarray, k, 0);
		}
	}

	return rarray;
}

void HeapSortRight(int array[], int size)
{
	int i;
	for (i = size / 2 - 1; i >= 0; i--) {
		AdjustDownArray(array, size, i);
	}

	for (i = 0; i < size) {
		Swap(&(array[0]), &(array[size - 1 - i]));

		AdjustDownArray(array, size - 1 - i, 0);
	}
}


void HeapSortWrong(int array[], int size)
{
	int i, j;
	for (j = 0; j < size; j++) {
		for (i = (size -j) / 2 - 1; i >= j; i--) {
			AdjustDownArray(array + j, size - j, i);	// 假设小堆
		}
	}
}

void Test()
{
	Heap	heap;
	int	array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
	int size = sizeof(array) / sizeof(int);

	HeapInit(&heap, array, size);
	HeapMake(&heap);
	for (int i = 0; i < heap.size; i++) {
		printf("%d ", heap.array[i]);
	}
	printf("\n");

	printf("Heap\n");
}

猜你喜欢

转载自blog.csdn.net/CDatreides/article/details/81481700