堆和哈夫曼树

堆分为最小堆和最大堆。最小堆指的是任意一个节点都有小于他的做儿子和右儿子。最大堆指的是任意一个节点大于打的左儿子右儿子。

最大堆的操作(堆得主要操作就是上滤和下滤)

插入:先将一个节点插入到堆得最后的位置然后上滤,如果他的父亲小于他,就把他父亲的值给他,继续循环,当退出循环的时候就是要插入的节点:

删除:删除堆顶元素,然后把最后一个元素拿上来做下滤;如果他的左右儿子中最大的那个大于他就把左右儿子中最大的那个值给堆顶,然后把左右儿子中最大的那个当做父节点继续循环,当循环退出的时候就是要插入的节点。

如何把一个堆调成最大堆:

先找到最后一个元素的的父节点然后做下滤,把这个小树调成最大堆然后依次循环。直至循环退出。

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 );
}

哈弗曼树(最优二叉树):

先把节点按权值大小存入最小堆,然后每次从节点中取出两个最小值并且合并构造哈夫曼树。

typedef struct TreeNode*Tree
struct Tree{
   int weight;
   Tree left;
   Tree right;
};
//假设有这个堆
Tree BuildTree(Heap H){
     Heap H;
     H=BuildMinHeap(H);//假设有这个方法
  //做H->size-1次循环 每次取出权值最小的两个节点进行合并
  for(int i=1;i<H->size;i++){
    Tree T = (Tree)malloc(sizeof(Tree));
    T->left = delete(H);
    T->right = delete(H);
    T->weight=T->left->weight+T->right->weight;
    Insert(H,T);
}
return delete(H);
}
typedef struct TreeNode*Tree
struct Tree{
   int weight;
   Tree left;
   Tree right;
};
//假设有这个堆
Tree BuildTree(Heap H){
     Heap H;
     H=BuildMinHeap(H);//假设有这个方法
  //做H->size-1次循环 每次取出权值最小的两个节点进行合并
  for(int i=1;i<H->size;i++){
    Tree T = (Tree)malloc(sizeof(Tree));
    T->left = delete(H);
    T->right = delete(H);
    T->weight=T->left->weight+T->right->weight;
    Insert(H,T);
}
return delete(H);
}

具体的实现过程

时间: 2024-08-02 12:05:21

堆和哈夫曼树的相关文章

数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉搜索树.红黑树.线索二叉树,它们在解决实际问题中有着非常重要的应用.本文主要从概念和一些基本操作上进行分类和总结. 一.概念总揽 (1) 堆 堆(heap order)是一种特殊的表,如果将它看做是一颗完全二叉树的层次序列,那么它具有如下的性质:每个节点的值都不大于其孩子的值,或每个节点的值都不小于其孩子的值

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int

【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找--方法一:顺序查找(时间复杂度O(n)) int SequentialSearch(St

数据结构-并查集和堆、哈夫曼树

一.并查集的定义 并查集是一种维护集合的数据结构,它的名字中"并"."查"."集".分别取自Union(合并).Find(查找).Set(集合). 合并:就是合并两个集合 查找:判断两个元素是否在一个集合 那么并查集是用什么实现的,就是一个数组, 对于同一个集合来说只存在一个根结点,且将其作为所属集合的标识. 二.并查集的基本操作 初始化,每个元素都是一个独立的集合,因此需要令所有的father[i] = i; for(int i = 1; i

数据结构学习笔记04树(堆 哈夫曼树 并查集)

一.堆(heap) 优先队列(Priority Queue):特殊的“队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序. 数组 : 插入 — 元素总是插入尾部 ~ O ( 1 ) 删除 — 查找最大(或最小)关键字 ~ O ( n ) 从数组中删去需要移动元素 ~ O( n ) 链表: 插入 — 元素总是插入链表的头部 ~ O ( 1 ) 删除 — 查找最大(或最小)关键字 ~ O ( n ) 删去结点 ~ O( 1 ) 有序数组: 插入 — 找到合适的位置

Fence Repair_霍夫曼树(最优树)_堆

Fence Repair TimeLimit:2000MS  MemoryLimit:65536K 64-bit integer IO format:%lld Problem Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of

树-堆结构练习——合并果子之哈夫曼树

树-堆结构练习——合并果子之哈夫曼树 Time Limit: 1000MS Memory limit: 65536K 题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了.多多在合并果子时总共消耗的体力等于每次合并所消耗体力之和. 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节

SDUT 堆结构练习——合并果子之哈夫曼树(丧心病狂heap)

树-堆结构练习--合并果子之哈夫曼树 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了.多多在合并果子时总共消耗的体力等于每次合并所消耗体力之和. 因为还要花大力气把这些果子搬回家,所以

SDUTOJ 2127 树-堆结构练习——合并果子之哈夫曼树

#include<iostream> #include<stdlib.h> #define N 30000 using namespace std; int a[N+1],o=0; typedef struct { int weight; int parent,lchild,rchild; }htnode; typedef struct { int weight; }htcode; void huffmanselect(htnode ht[],int k,int *s1,int *