zoukankan      html  css  js  c++  java
  • 堆及其操作

    堆及其操作

    • 最大堆的创建
    • 最大堆的插入操作
    • 最大堆的删除操作
    • 建立最大堆

    相关的代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    #define MAXDATA 1000  //该值根据具体情况定义为大于堆中所有可能元素的值
    #define ERROR -1 //错误标志 应根据具体情况定义为堆中不可能出现的元素值
    
    //堆的C语言描述
    struct HNode
    {
    	int* Data;  //存储元素的数组
    	int Size;  //堆中当前元素的个数
    	int Capacity;  //堆的最大容量
    };
    
    struct HNode* CreatHeap(int MaxSize)
    {
    	struct HNode* H = (struct HNode*)malloc(sizeof(struct HNode));
    	H->Data = (int *)malloc((MaxSize + 1) * sizeof(int));
    	H->Size = 0;
    	H->Capacity = MaxSize;
    	H->Data[0] = MAXDATA;  //定义哨兵为大于堆中所有可能元素的值
    	return H;
    }
    //作用:判断当前堆是否为空
    bool IsFull(struct HNode* H)
    {
    	return (H->Capacity == H->Size);
    }
    
    //作用:最大堆的插入操作
    //      将元素X插入最大堆H,其中H->Data[0]已经定义为哨兵
    bool Insert(struct HNode* H,int x)
    {
    	int i;
    	if (IsFull(H))
    	{
    		printf("堆已满.
    ");
    		return false;
    	}
    
    	i = ++H->Size;  //i指向插入后堆中最后一个元素的位置
    	for ( ; H->Data[i/2] < x ; i = i / 2)
    	{
    		H->Data[i] = H->Data[i / 2];
    	}
    	H->Data[i] = x;
    	return true;
    }
    
    //判断当前堆中元素是否为空
    bool IsEmpty(struct HNode* H)
    {
    	return (H->Size == 0);
    }
    
    //作用:从最大堆中取出键值最大的元素,并删除一个节点
    int DeleteMax(struct HNode* H)
    {
    	int Parent, Child;
    	int MaxItem;
    	int X;
    	if (IsEmpty(H))
    	{
    		printf("当前堆为空.
    ");
    		return false;
    	}
    	MaxItem = H->Data[1];  //取出根节点存放的最大值
    	X = H->Data[H->Size--];  //用最大堆中最后一个元素从根节点开始向上过滤下层节点
    	                         //注意当前堆的规模要减小
    
    	for (Parent = 1;Parent * 2 <= H->Size;Parent = Child)
    	{
    		Child = Parent * 2;
    		if ((Child != H->Size) && (H->Data[Child] < H->Data[Child + 1]))
    		{
    			Child++;  //Child指向左右子节点的较大者
    		}
    		if (X >= H->Data[Child])
    		{
    			break;
    		}
    		else
    		{
    			H->Data[Parent] = H->Data[Child];
    		}
    	}
    	H->Data[Parent] = X;
    	return true;
    }
    //作用:下滤 将H->Data[p]为根的子堆调整为最大堆
    void PercDown(struct HNode* H,int p)
    {
    	int Parent;
    	int Child;
    	int x;
    	x = H->Data[p];  //取出根节点存放的值
    	//退出循环的条件:当前的节点都被扫描了一遍
    	for (Parent = p; Parent * 2 <= H->Size; Parent = Child)  
    	{
    		Child = Parent * 2;
    		
    		if (H->Data[Child] < H->Data[Child + 1])
    		{
    			//当前指向了左右子节点较大值
    			Child = Child + 1;  
    		}
    		if (x >= H->Data[Child])
    		{
    			//找到了合适的位置
    			break;
    		}
    		else
    		{
    			//交换父节点和较大子节点的位置
    			H->Data[Parent] = H->Data[Child];
    		}
    	}
    	H->Data[Parent] = x;
    }
    
    //作用:最大堆的建立
    //这里假设所有H->Size个元素已经存在与H->Data[]中
    void BuildHeap(struct HNode* H)
    {
    	int i;
    	//从最后一个节点的父节点开始,到根节点
    	for (i = H->Size / 2;i > 0;i--)
    	{
    		PercDown(H,i);
    	}
    
    }
    void PrintHeap(struct HNode* H)
    {
    	for (int i = 1;i <= H->Size;i++)
    	{
    		printf("%d.
    ",H->Data[i]);
    	}
    }
    int main()
    {
    	struct HNode*  Heap = CreatHeap(15);
    	int a[] = {18,25,44,58,10,31};
    	for (int i = 1;i <= sizeof(a) / sizeof(a[0]);i++)
    	{
    		Heap->Data[i] = a[i - 1];
    		Heap->Size++;
    	}
    	printf("构建堆:
    ");
    	BuildHeap(Heap);
    	PrintHeap(Heap);
    	printf("删除元素后:
    ");
    	DeleteMax(Heap);
    	PrintHeap(Heap);
    	printf("插入元素后:
    ");
    	Insert(Heap,58);
    	PrintHeap(Heap);
    	system("pause");
    	return 0;
    }
    

    参考资料:
    1 https://www.jianshu.com/p/21bef3fc3030 最大堆(创建、删除、插入和堆排序)
    2 《数据结构》(第2版) 陈越主编

  • 相关阅读:
    LeetCode对撞指针汇总
    167. Two Sum II
    215. Kth Largest Element in an Array
    2018Action Recognition from Skeleton Data via Analogical Generalization over Qualitative Representations
    题解 Educational Codeforces Round 84 (Rated for Div. 2) (CF1327)
    题解 JZPKIL
    题解 八省联考2018 / 九省联考2018
    题解 六省联考2017
    题解 Codeforces Round #621 (Div. 1 + Div. 2) (CF1307)
    题解Codeforces Round #620 (Div. 2)
  • 原文地址:https://www.cnblogs.com/Manual-Linux/p/11344403.html
Copyright © 2011-2022 走看看