树(下)
1.堆
这里所讲的堆并不是堆栈,而是二叉堆。原理上就是一个优先队列。
优先队列是特殊的队列,从堆中取出元素的顺序是依照元素的权值大小,而不是元素进入队列的先后顺序。采用完全二叉树存储的优先队列 称为堆。
堆又分为最大堆和最小堆,插入节点和删除节点可以看我的另外一个博客——二叉堆。里面也有例题。
https://mp.csdn.net/console/editor/html/104187825
这里补充如何建堆。
例如最大堆的建立:
方法一:将已经存在的N个元素按最大堆的要求存放在一个一维数组中。可以通过最大堆的插入操作,将N个元素一个个相继插入到一个初始为空的堆中去,其时间代价最大为O(N logN)。
方法二:在线性时间复杂度下建立最大堆。具体分两步进行: 第一步,将N个元素按输入顺序存入二叉树中,这一步只要求满足完全二叉树的结构特性,而不管其有序性。第二步,调整各结点元素,以满足最大堆的有序特性。
简而言之就是从最后一个具有儿子的节点开始调整将每一个节点都变成一个堆。
void tiaozheng( Maxheap h,int p)//h为建的空堆
{//将H中以h->data[p]为根的子堆调整为最大堆
int parent,child;
int 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//否则交换位置
h->data[parent]=h->data[child];
}
h->data[parent]=x;
}
void build( Maxheap h)
{
int i;
for(i=h->size/2;i>0;i--)//从最后一个结点的父节点开始,到根结点1
tiaozheng(h,i);
}
2.哈夫曼树
假设有n个权值{w1 ,w2 , …… , wn} ,构造有n个叶子的二叉树,每个叶子的权值是n个权值之一。这样的二叉树也许可以构造多个,其中必有一个(或几个)是带权路径长度最小的。达到带权路径长度最小的二叉树就称为最优二叉树或哈夫曼树。
那么什么是带权路径长度呢?
二叉树的每个叶子结点带有权值 ,从根结点到每个叶子结点的长度为它的 权路径长度,则每个叶子结点的带权路径长度之和就是这棵树的带权路径长度。
原理最小堆
struct node
{
int v;
struct node *l,*r;
};
struct node *Huffman(Minheap h)//h为建立的空堆
{
//假设h->size个权值已经存在h->data[]->v里
int i,x;
struct node* t;
build(h);//将h->tata[]按权值v调整为最小堆
x=h->size;
for(i=1;i<x;i++)
{
t=(struct node *)malloc(sizeof(struct node));
t->l=deletemin(h);//删除左右儿子
t->r=deletemin(h);
t->v=t->l->v+t->r->v;//t的权值等于左右儿子的权值之和
Insert(h,t);//将新t插入最小堆
}
return deletemin(h);
};
3.集合与运算
见博客并查集