• 堆的操作集


    什么是堆

    • 优先队列( Priority Queue):特殊的“队列” ,取出元素的顺序是
      依照元素的优先权(关键字) 大小,而不是元素进入队列的先后顺序

    问题:如何组织优先队列?
     一般的数组、链表?
     有序的数组或者链表?
     二叉搜索树? AVL树

    • 产生了堆这种数据结构,知道基本操作集

    • 增查的操作方式,创建的方法

    测试代码

    /*!
     * file 堆的操作集.cpp
     *
     * author ranjiewen
     * date 2017/04/06 23:25
     *
     * 
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct HNode *Heap;  //堆的类型定义
    typedef int Elementype;
    
    struct HNode 
    {
    	Elementype *Data; //存储元素的数组  //堆是完全二叉树,用数组存储利用率高
    	int size; //堆中当前元素的个数
    	int capacity; //堆的最大容量
    };
    
    typedef Heap MaxHeap; //最大堆
    typedef Heap MinHeap; //最小堆
    
    #define MAXDATA 1000  //该值应根据情况定义为大于堆中所有可能元素的值
    
    MaxHeap CreateHeap(int MaxSize)
    {
    	//创建容量为MaxSize的空的最大堆
    	MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));
    	H->Data = (Elementype*)malloc((MaxSize+1)*sizeof(Elementype));
    	H->size = 0;
    	H->capacity = MaxSize;
    	H->Data[0] = MAXDATA; //定义“哨兵”为大于堆中所有可能元素的值
    	return H;
    }
    
    int IsFull(MaxHeap H)
    {
    	return H->size == H->capacity;
    }
    
    //bool
    int Insert(MaxHeap H, Elementype x)
    {
    	//将元素x插入最大堆H,其中H->Data[0]已经定义为哨兵
    	int i;
    	if (IsFull(H))
    	{
    		printf("最大堆已满!");
    		return false;
    	}
    	i = ++H->size; //i指向插入后堆中的最后一个元素的位置
    	//先直接到插入到数组最后的元素,然后在调整堆
    	for (; H->Data[i / 2] < x;i/=2)  //父节点比它小
    	{
    		H->Data[i] = H->Data[i/2]; // 和父节点交换
    	}
    	H->Data[i] = x; //找到插入位置,插入
    
    	return 1;
    }
    
    #define  ERROR -1  //错误标识,定义为堆中不可能出现的元素值
    
    bool IsEmpty(MaxHeap H)
    {
    	return H->size == 0;
    }
    
    Elementype DeleteMax(MaxHeap H)
    {
    	//从最大堆H中取出键值为最大的元素,并删除一个结点
    	int Parent, Child;
    	Elementype MaxItem, x;
    
    	if (IsEmpty(H))
    	{
    		printf("最大堆已为空");
    		return ERROR;
    	}
    	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   /* 下滤X */
    		{
    			H->Data[Parent] = H->Data[Child];
    		}
    	}
    	H->Data[Parent] = x;
    
    	return MaxItem;
    }
    
    /*------------建造最大堆----------------------*/
    
    void PrecDown(MaxHeap H, int p)
    {
    	//下滤:将H中以H->Data[p]为根的子堆调整为最大堆
    	int Parent, Child;
    	Elementype x;
    
    	x = H->Data[p]; //取出根节点存放的值
    	for (Parent = p; 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   /* 下滤X */
    		{
    			H->Data[Parent] = H->Data[Child];
    		}
    	}
    	H->Data[Parent] = x;
    }
    
    void BuildHeap(MaxHeap H)
    {
    	//调整H->Data[]中的元素,是满足最大堆的有序性
        //这里假设所有H->size个元素已经存在H->Data[]中
    	int i;
    	//从最后一个结点的父节点开始,到根结点
    	for (i = H->size / 2; i > 0;i--)
    	{
    		PrecDown(H, i);
    	}
    }
    
    
    int main()
    {
    	MaxHeap H;
    	H = CreateHeap(10);
    	for (int i = 0; i < 10;i++)
    	{
    		Insert(H, i + 10);
    	}
    	for (int i = 0; i < H->size;i++)
    	{
    		printf("%d ", H->Data[i + 1]);
    	}
    	printf("
    ");
    
    	for (int i = 0; i < H->size; i++)
    	{
    		H->Data[i + 1] = i + 10;
    	}
    	BuildHeap(H);
    	for (int i = 0; i < H->size; i++)
    	{
    		printf("%d ", H->Data[i + 1]);
    	}
    	printf("
    ");
    	return 0;
    }
    
    
    
  • 相关阅读:
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业
    第一次个人作业
    个人总结-人生如戏
    第二次结对编程
    第一次结对作业
    第二次个人编程作业:代码互改
    第一次个人编程作业
    软件工与UML程第一次作业
  • 原文地址:https://www.cnblogs.com/ranjiewen/p/6680720.html
Copyright © 2020-2023  润新知