树下
第一讲
一.堆
什么是堆?
在讲堆之前,我们先看看什么是优先队列。
优先队列:是一种特殊的队列,从名称上看,优先,顾名思义,取出的元素是按照一定的优先级出队的,而不是元素进入队列的先后顺序。
优先队列的完全二叉树表示
堆的两个特性:
结构性:用数组表示的完全二叉树。
有序性:任一结点的关键字是其子树所有结点的最大值(或最小值)。
由最大值和最小值我们可以引出一个新概念“最大堆”“最小堆”
最大堆:每个结点的元素值不小于其子结点的元素值。
最小堆:每个结点的元素值不大于其子结点的元素值。
主要在最大堆的操作上面,因为最大堆会了,最小堆自然就不成问题了
最大堆的创建
typedef struct HeapStruct *MaxHeap;
struct HeapStruct
{
ElementType *Elements[];//存储堆元素
int Size;//堆元素个数
int Capacity;//堆的最大容量
}
MaxHeap Create(int MaxSize)
{
MaxHeap H=malloc(sizeof(struct Heapstruct));
H->Elements=malloc((MaxSize+1)*sizeof(sizeof(ElementType));
H->Size=0;
H->Capacity=MaxSize;
H->Elements[0]=Maxdata;//把Maxdata变成mindata也同样使用于创建最小堆
return
最大堆的插入
我们的算法就是,将新增的结点插入到从其父结点到根结点的有序序列中,我们就能保证最大堆的有序性并完成插入。
void Insert(MaxHeap H,ElementType item)
{
int i;
if(IsFull(H))
{
printf("堆满");
return;
}
i=++H->Size;//i指向插入堆中的最后一个元素的位置
for(;H->Elements[i/2]<item;i/=2)
{
H->Elements[i]=H->Elements[i/2];//向下过滤结点
}
H->Elements[i]=item;//进行插入
}
最大堆的删除
我们最大堆的删除操作的算法就是,取出根结点,也就是我们最大的元素,同时删除堆的一个结点
ElementType DeleteMax(MaxHeap H)
{
int Parent,Child;
ElementType MaxItem,temp;
if(IsEmpty)//堆满
{
printf("堆满");
return;
}
MaxItem=H->Elements[1];//取出最大值,根结点
temp=H->Elements[H->Size--];
for(Parent=1;Parent*2<=H->Size;Parent=Child)//用最大堆的最后一个元素从根结点开始向上过滤下层结点
{
Child=Parent*2;
if((Child!=H->Size)&&(H->Elements[Child]<H->Elements[Child+2]))
{
Child++;//指向较大的一方
}
if(temp>=H->Elements[Child])
break;
else
H->Elements[Parent]=H->Elements[Child];
}
H->Elements[Parent]=temp;
return MaxItem;
}
第二讲
一.赫夫曼树的定义及原理
赫夫曼大叔说,从树的一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径长度,然而树的路径长度等于从根结点到树的每一个结点的路径长度之和,带权路径最小的二叉树被称为赫夫曼树,也称为最优二叉树。
赫夫曼算法(用来查找赫夫曼树)描述:
根据给定的n个权值{w1,w2…}构成的n棵二叉树的集合F={T1,T2…},其中每棵二叉树Ti中只有一个带权为wi根结点,其左右子树均为空。在F中选取两棵根结点的权值最小的树作为左右子树,然后构造一个新的二叉树,并且新的二叉树的根结点的权值为其左右树上根结点的权值之和;在F中删除这两棵树,同时将新得到的二叉树加入F中,重复上述步骤,直到F只含一棵树为止。然后这棵树就是赫夫曼树。说了那么多,其实我也不怎么懂…
心得:通过这章结的学习,树,和森林看似复杂,但是我们可以通过二叉树之类的有一定规律的树来规范它,一旦有了规律,我们顺着规律走,就柳暗花明了,其次,以前喜欢用数组,是因为其简单易操作,但是现在发现,它太浪费空间了,而树的结构节省了很多空间,提高了效率。
来源:CSDN
作者:JT518721
链接:https://blog.csdn.net/JT518721/article/details/104417787