《数据结构与算法》第四次
二叉树的创建、销毁、插入、删除、遍历等操作的实现(下)
实验目的:
- 掌握二叉树的存储结构和相关算法。
- 掌握哈夫曼树的构建和哈夫曼编码的算法。
实验内容:
建立一个霍夫曼树,并输出编码表。
实验步骤:
1.参考代码,建立完整的霍夫曼树
2.并输出这课霍夫曼树的编码表。
参考提示:
1.在bianryTreeNode的声明里增加一个string类型的变量code,用来存储binaryTreeNode类型结点的霍夫曼编码。
2.编写一个输出霍夫曼编码表的函数在主函数里调用,可以采用一边深度遍历已经建立好的霍夫曼树,一边维护code变量的方法实现霍夫曼编码并输出。
3.主函数可以为以下形式
输出霍夫曼编码需要访问二叉树根节点,但是root变量是私有成员,所以需要在里新定义个获取根节点的成员函数(如下图)
函数的实现如下图所示。
江米条想说的(简单快速记忆):
{
哈夫曼编码应用广泛,JPEG中就应用了哈夫曼编码。 那么什么是哈夫曼树呢?哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。
最优二叉树,简单吧。就是每次从数据里面拿出最小的两个数,求和,然后把这个数和剩下的数里面再挑最小的两个,再求和。
以此类推。生成的树就是路径长度最短的最优二叉树。它是一颗大根堆的树。
那我为什么要用在这个程序里面用minHeap.h(小根堆)呢,因为我要每次都寻找最小的两个数呀,所以每次加完了就把得到的结果插入小根堆中。不用担心插入的数据出错,如果担心的话,可以看小根堆插入数据的算法。
最后输出的霍夫曼编码就是从上到下走过的路径的编码,每往左走一次,多记一个0;往右走一次多记一个1。
顺序千万不能错,小根堆的数据插入是有规矩的,插入数据之后,需要调整位置再次成为小根堆,合成的数据和集合里面的数据不能乱提出来,否则霍夫曼编码的01的位置会出错!可以看看下图,每次插入数据的时候,小根堆是怎样维护,使它永远是小根堆的。
}
附加代码(小根堆插入数据时候的排序问题):
template<class T>
void minHeap<T>::push(const T& theElement)
{
if (heapSize == arrayLength - 1)//大小不够的话,就将数组扩大一倍
{
changeLength1D(heap, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
int currentNode = ++heapSize;
while (currentNode != 1 && heap[currentNode / 2] > theElement)
{
heap[currentNode] = heap[currentNode / 2]; //
currentNode /= 2; // 元素移动到它的父母那里
}
heap[currentNode] = theElement;
}
附霍夫曼编码图:
A对应的编码:11
B对应的编码:10
C对应的编码:00
D对应的编码:011
E对应的编码:010
实验代码:
// Huffman tree
#include <iostream>
#include "minHeap.h"
#include"binaryTreeNode.h"
#include "linkedBinaryTree.h"
#include "huffmanNode.h"
#include<cstring>
using namespace std;
template <class T>
linkedBinaryTree<int>* huffmanTree(T weight[], int n)
{// Generate Huffman tree with weights weight[1:n], n >= 1.
// create an array of single node trees
huffmanNode<T> *hNode = new huffmanNode<T> [n + 1];
linkedBinaryTree<int> emptyTree;
for (int i = 1; i <= n; i++)
{
hNode[i].weight = weight[i];
hNode[i].tree = new linkedBinaryTree<int>;
hNode[i].tree->makeTree(i, emptyTree, emptyTree);
}
// make node array into a min heap
minHeap<huffmanNode<T> > heap(1);
heap.initialize(hNode, n);
// repeatedly combine trees from min heap
// until only one tree remains
huffmanNode<T> w, x, y;
linkedBinaryTree<int> *z;
for (int i = 1; i < n; i++)
{
// remove two lightest trees from the min heap
x = heap.top(); heap.pop();
y = heap.top(); heap.pop();
// combine into a single tree
z = new linkedBinaryTree<int>;
z->makeTree(0, *x.tree, *y.tree);
w.weight = x.weight + y.weight;
w.tree = z;
heap.push(w);
delete x.tree;
delete y.tree;
}
// destructor for min heap deletes hNode
return heap.top().tree;
}
template<class T>
void setHuffmanCode(binaryTreeNode<T>*t)
{
if (t->leftChild != NULL)
{
t->leftChild->code = t->code;
t->leftChild->code.append("0");//往左走的路线是0
}
if (t->rightChild != NULL)
{
t->rightChild->code = t->code;
t->rightChild->code.append("1");//往右走的路线是1
}
}
template<class T>
void output(binaryTreeNode<T>*t)
{
if (t->leftChild == NULL&&t->rightChild == NULL)
cout << "节点" << t->element << "的霍夫曼编码为" << t->code << endl;
}
template<class E>
void huffmanCode(linkedBinaryTree<E>*h)
{
h->preOrder(setHuffmanCode);
h->preOrder(output);
}
int main(void)
{
int a[11];
int n = 10;
for (int i = 1; i <= n; i++)
a[i] = 2 * i;
linkedBinaryTree<int> *x = huffmanTree(a, n);
huffmanCode(x);
return 0;
}
代码链接:https://download.csdn.net/download/lzjstudy/10557261
如有问题,请联系我 QQ:1239825268
备注 CSDN
共勉!