堆:将数据按完全二叉树的顺序存储方式存储在一维数组

数组中的数据值同时满足 a[i]>=2a[i]+1 和  a[i]>=2a[i]+2

或者同时满足a[i]<=2a[i]+1 和 a[i]<=2a[i]-1

堆的特性:是完全二叉树

大堆,每个双亲节点的值总是大于(等于)子节点的值。

小堆,每个双亲节点的值总是小于(等于)子节点的值。

数据结构中的堆和内存中的堆的区别:

数据结构中的堆是一种数据的存储结构,是算法,而内存堆区是内存中区别于栈区、静态常量区的一个数据存储区域。

创建堆:讲数组(序列)在逻辑上看成完全二叉树,然后通过算法从倒数第一个非叶子节点进行调整,最后得到堆。

插入元素时:将元素插入到数组的尾上,然后将其与父节点对比向上调整。

删除:将顶元素与最后一个元素交换,再进行调整,最后将记录元素个数的那个值减1

堆排序:有两种,1 将数组放到堆中,一次取堆顶元素放回数组,并删除对顶元素    (额外开辟空间)

                             2  将数组放到堆中,调整完后形成需要的堆,然后依次取堆顶元素  (不开辟空间,浪费时间)

TOPk问题,取前面的几个数据建小堆,后面的数据和堆中的数据对比,大于堆顶则替换堆顶元素,然后向下调整


typedef int DataType;

typedef struct Heap 

   {  

             int *arr;  

             int capacity;  

             int size;

}Heap;

// 销毁堆 
void DestroyHeap(Heap* heap)
{
	if (heap == NULL)
	{
		return;
	}
	//capacity和数组可以不用再管
	heap->size = 0;
	return;
}

// 获取堆中有效元素个数 
int SizeHeap(Heap* heap)
{
	if (heap == NULL)
	{
		return 0;
	}
	return heap->size;
}

// 检测堆是否为空 
int EmptyHeap(Heap* heap)
{
	if (heap == NULL)
	{
		return 0;
	}
	return heap->size == 0 ? 1 : 0;
}

//堆化
void heapify(int a[], int size, int index) {
	// index 是不是叶子结点? index 有没有孩子?
	// index 有没有左孩子? index 左孩子下标是否越界?
	if (2 * index + 1 >= size) 
	{
		return;
	}

	int min = 2 * index + 1;
	if (2 * index + 2 < size && a[2 * index + 2] < a[2 * index + 1]) {
		min = 2 * index + 2;
	}

	if (a[index] <= a[min])
	{
		return;
	}

	int t = a[min];
	a[min] = a[index];
	a[index] = t;

	heapify(a, size, min);
}

void HeapInit(Heap *heap, int a[], int size) {
	for (int i = 0; i < size; i++) {
		heap->arr[i] = a[i];
	}
	heap->size = size;

	createHeap(heap->arr, heap->size);
}


void adjustUp(int a[], int index) {
	while (index > 0) {
		if (index == 0) {
			return;
		}

		int parent = (index - 1) / 2;
		if (a[parent] <= a[index]) {
			return;
		}

		int t = a[parent];
		a[parent] = a[index];
		a[index] = t;

		index = parent;
	}
}

void HeapPush(Heap *heap, int val) {
	heap->arr[heap->size++] = val;
	adjustUp(heap->arr, heap->size - 1);
}

void HeapPop(Heap *heap) {
	assert(heap->size > 0);
	heap->arr[0] = heap->arr[heap->size - 1];
	heap->size--;

	heapify(heap->arr, heap->size, 0);
}


void createHeap(int arr[], int size)
{
	//(size-2)/2 划分开始的界限,从最后一个非叶节点
	for (int i = (size - 2) / 2; i >= 0; i--)
	{
		int index = i;
		while (1) {
			int left = 2 * index + 1;
			int right = 2 * index + 2;

			if (left >= size) {
				return;
			}

			int min = left;
			if (right < size && arr[right] < arr[left]) {
				min = right;
			}

			if (arr[index] <= arr[min]) {
				return;
			}

			int t = arr[min];
			arr[min] = arr[index];
			arr[index] = t;

			index = min;
		}
	}
}

int main()
{
	int arr[10] = { 5, 2, 6, 9, 8, 3, 0, 4, 1, 7 };
	int size = sizeof(arr) / sizeof(arr[0]);
	//Heap* 
	createHeap(arr, size);
	

	return 0;
}

 

posted on 2019-07-24 22:10  青椒炒肉没有肉  阅读(192)  评论(0编辑  收藏  举报

导航