哈夫曼树的创建

来源:互联网 发布:linux openssl安装 编辑:程序博客网 时间:2024/06/11 19:39

    相信刚踏入计算机系的同学们学习数据结构的时候都碰到了哈夫曼树,哈夫曼树也称最优二叉树,它的定义是:在给定的一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带全路径长度最小的二叉树称为哈夫曼树。哈夫曼树在实际中有着广泛的应用,比如信息检索,编译码。话不多说直接上代码跟注释:

   //此代码是用vs2015编译器搞定的,vs的一枚粉丝。

#include<iostream>
using namespace std;

//先要创建哈夫曼树结点的结构体
typedef struct _HUFFMAN_NODE
{
char Str;   //用于记录字符
double frequence;     //用于记录权值
int symbol;    //标志,左子树为1,右子树为0
_HUFFMAN_NODE *left;    //左子树
_HUFFMAN_NODE *right;   //右子树
_HUFFMAN_NODE *parent;  //父结点
}_HUFFMAN_NODE;

//创建好结构体后,定义一个函数创建一个哈夫曼结点
_HUFFMAN_NODE* Create_New_Node(char str, double frq)
{
_HUFFMAN_NODE* pNode = (_HUFFMAN_NODE *)malloc(sizeof(_HUFFMAN_NODE));
if (pNode != NULL)
{
pNode->Str=str;
pNode->frequence = frq;
pNode->left = NULL;
pNode->right = NULL;
pNode->parent = NULL;
}
return pNode;
}

//因为平常写算法的同学肯定会频繁使用比较、替换、排序、遍历等操作,所以最好习惯把他们定义成函数,方便调用,提高编写算法的效率。

//比较函数(两个哈夫曼结点权值的大小 )
bool Compare(_HUFFMAN_NODE*v1,_HUFFMAN_NODE* v2)
{
return v1->frequence > v2->frequence ? true: false;
}


//交换函数
void Swap(_HUFFMAN_NODE** v3, _HUFFMAN_NODE** v4)
{
_HUFFMAN_NODE *temp;
temp = *v3;
*v3 = *v4;
*v4 = temp;
}


//排序函数(冒泡算法),根据权值大小将结点由小到大排序。
void Bubble_Sort(_HUFFMAN_NODE* Array[],int length,bool Compare(_HUFFMAN_NODE*, _HUFFMAN_NODE*),void Swap(_HUFFMAN_NODE**, _HUFFMAN_NODE**))//在此处需要用到之前定义的比较大小函数和交换值函数,将两个函数当作参数传进来
{
int outer;
int inner;
for (outer = 0; outer < length - 1; outer++)
{
for (inner = 0; inner < length - outer - 1; inner++)
{
if (Compare(Array[inner], Array[inner + 1]))
{
Swap(&Array[inner], &Array[inner + 1]);  // (int* v1,int* v2)传参时(&v1,&v2)
}
}
}
}


//创建哈夫曼树(重点哦)
_HUFFMAN_NODE* CREATE_HUFFMAN_TREE(_HUFFMAN_NODE* HuffmanNode[], int length)
{
_HUFFMAN_NODE* head = NULL;


while (length > 1)//n个结点需要n-1次结合
{
Bubble_Sort(HuffmanNode, length, Compare, Swap);//每次结合之前先排序
head = Create_New_Node('0', HuffmanNode[0]->frequence + HuffmanNode[1]->frequence);//创建合成的结点
head->left = HuffmanNode[0];//将排序后最小权值的两个结点分别作为合成结点的左右孩子
head->right = HuffmanNode[1];
HuffmanNode[0]->parent = head;//
HuffmanNode[0]->symbol = 1;//标志
HuffmanNode[1]->parent=head;
HuffmanNode[1]->symbol = 0;//标志
memmove(&HuffmanNode[0], &HuffmanNode[2], sizeof(_HUFFMAN_NODE*)*(length-2));//调用系统函数,此函数用于字符串拷贝,从第二个参数指定的位置开始拷贝x长度(第三个参数)的字符串到从第一个参数开始的位置

HuffmanNode[length - 2] = head;//把新生成的根结点加入到数组中
length--;
}
return head;
}


//打印某个结点的哈夫曼编码(逆向打印,如果看着不爽自己先把数据存入数组再倒着打印,这里就不废话了相信大家都懂)
void Print_Code_For_Str(_HUFFMAN_NODE* pNode, _HUFFMAN_NODE* head)
{
if (NULL == pNode || NULL == head)
return;
cout << "哈夫曼逆向编码:" << endl;
while (pNode!=head) 
{
printf("%d", pNode->symbol);
pNode = pNode->parent;
}
cout << endl;
return;
}


//测试函数
void Test()
{
_HUFFMAN_NODE* node1 = NULL;
_HUFFMAN_NODE* node2 = NULL;
_HUFFMAN_NODE* node3 = NULL;
_HUFFMAN_NODE* node4 = NULL;


_HUFFMAN_NODE* test[] = 

node1 = Create_New_Node('a', 0.1),
node2 = Create_New_Node('b', 0.2),
node3 = Create_New_Node('c', 0.3),
node4 = Create_New_Node('d', 0.4),
};


_HUFFMAN_NODE* head = CREATE_HUFFMAN_TREE(test, sizeof(test) / sizeof(_HUFFMAN_NODE*));
Print_Code_For_Str(node1, head);
Print_Code_For_Str(node2, head);
Print_Code_For_Str(node3, head);
Print_Code_For_Str(node4, head);
system("pause");
}
int main()
{
Test();
    return 0;
}
结束了。希望这个哈夫曼树的创建可以帮到需要的同学。

   


原创粉丝点击