来源:互联网 发布:网络经济犯罪的特点有 编辑:程序博客网 时间:2024/05/16 00:56
数据结构中的堆,是优先队列(Priority Queue):特殊的“队列” ,取出元素的顺序是依照元素的优先权(关键字) 大小,而不是元素进入队列的先后顺序。
内存中的堆,栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。每次的malloc就是申请堆空间。
堆的存储方式
将堆(优先队列)用一种完全二叉树的方式来表示,与搜索二叉树不同的是,根节点永远是最大的或者最小的!
因此用树的顺序存储的方式来搞

其实优先队列可以用线性结构的,但是线型结构的操作时间复杂度比较高,肯定不如用完全二叉树的方式来做
堆的插入删除
插入操作:复杂度就是堆的深度,现将插入的数放到数组的最后,然后不断地循环与父结点比较,并且调换。
删除操作:复杂度就是堆的深度,因为是优先队列,所以每次删除的是最上面的根节点。先删除根节点,然后将数组最后一个数放到根节点的位置。循环的与子节点比较,并且调换。直到做出一个全新的堆。

typedef struct HNode *Heap; /* 堆的类型定义 */struct HNode {    ElementType *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 = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));    H->Size = 0;    H->Capacity = MaxSize;    H->Data[0] = MAXDATA; /* 定义"哨兵"为大于堆中所有可能元素的值*/     return H;} bool IsFull( MaxHeap H ){    return (H->Size == H->Capacity);} //堆的插入bool Insert( MaxHeap H, ElementType 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]; /* 上滤X */    H->Data[i] = X; /* 将X插入 */    return true;} #define ERROR -1 /* 错误标识应根据具体情况定义为堆中不可能出现的元素值 */ bool IsEmpty( MaxHeap H ){    return (H->Size == 0);}//堆的删除 ElementType DeleteMax( MaxHeap H ){ /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */    int Parent, Child;    ElementType 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 PercDown( MaxHeap H, int p ){ /* 下滤:将H中以H->Data[p]为根的子堆调整为最大堆 ,前提是该根下的两个已经是堆*/    int Parent, Child;    ElementType 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;     /* 从最后一个结点的父节点开始,到根结点1 */    for( i = H->Size/2; i>0; i-- )        PercDown( H, i );}//建造最大堆,使用先建立空堆后一个一个元素插入堆的形式#define MAXN 1001#define MINH -10001int H[MAXN], size;void Create (){size = 0;H[0] = MINH;/*设置“岗哨” */}void Insert ( int X ){/* 将X插入H。这里省略检查堆是否已满的代码 */int i;for (i=++size; H[i/2] > X; i/=2)H[i] = H[i/2];H[i] = X;}for (i=0; i<n; i++) { /*以逐个插入方式建堆 */scanf("%d", &x);Insert(x);}