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

    数组中的数据值同时满足 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;
    }
    
    住进火焰就成为萤火虫。
  • 相关阅读:
    无法卸载Visual Studio 2005,提示:"H:\vs\vs_setup.msi could not be opened"
    在两个DB的table之间同步数据
    用于标记系统是否需要重启动的注册表键值
    提高性能——存储过程最佳实践 [译自MSDN]
    几个常见的位运算问题
    [存档] 非递归后根遍历二叉树
    [存档] 用真值表设计非递归二叉树遍历算法
    补码
    卸载Google Chrome导致Outlook, Word不能打开超链接
    编程题: 将一个矩阵(二维数组)顺时针旋转90度
  • 原文地址:https://www.cnblogs.com/fengkun/p/11241221.html
Copyright © 2020-2023  润新知