不知道为什么,我写的代码都是又臭又长。
直接上代码:
#include <iostream> #include <cstdarg> using namespace std; class Node{ public: int weight; int parent, lChildren, rChildren; Node(int weight, int parent, int lChildren, int rChildren): weight(weight), parent(parent), lChildren(lChildren), rChildren(rChildren) { } void printNode(){ cout<<"weight = "<<weight<<", "; cout<<"parent = "<<parent<<", "; cout<<"lChildren = "<<lChildren<<", "; cout<<"rChildren = "<<rChildren<<endl; } }; class Tree{ Node **nodes; char** huffmanCodec; int length,rPos; int mNum; /**给Tree实例增加Node。 * **/ void addNode(Node *node){ if(!node){ cout<<"addNode中,指针为NULL"<<endl; return; } for(int i = 0; i < length; i++){ if(node == nodes[i])//如果存在了就不必加到里面了。。 return; } nodes[length++] = node; } /**从数组array中找到最小的两个数值,赋给v1和v2 * **/ void findSmallest2ValueInArray(int *array, int length, int *v1, int *v2, int *v1Pos, int *v2Pos){ int t = 0; for(int i = 0; i < length; i++){ if(array[i] < 0) continue; ++t; if(t == 1){ *v1 = array[i]; *v1Pos = i; }else if (t == 2){ *v2 = array[i]; *v2Pos = i; }else{ if(*v1 > array[i]){ if(*v1 < *v2){ *v2 = *v1; *v2Pos = *v1Pos; } *v1 = array[i]; *v1Pos = i; }else if(*v2 > array[i]){ *v2 = array[i]; *v2Pos = i; } } } } /** *从当前Tree中找到给定node的下标。生成huffman编码用的。 * **/ int findNodePosViaNode(Node *node){ for(int i = 0; i < length; i++){ if(nodes[i] == node){ return i; } } return -1; } /** *从当前Tree中找到给定Weight的node的下标, 并且该node没有parent。生成树结构用的。 * **/ int findNodePosViaWeight(int value, bool isForParent, bool isTheSameWeightNode){ for(int i = 0; i < length; i++){ if(nodes[i]->parent == -1 && nodes[i]->weight == value && !isForParent && !isTheSameWeightNode){ return i; } } return -1; } /** *从头至尾找到叶子结点。 * **/ int findHuffmanNodePos(){ static int mark;//默认初始化为0 for(int i = mark; i < length; i++){ if(nodes[i]->lChildren == -1 && nodes[i]->rChildren == -1){ mark = i + 1; return i; } } return -1; } /** *初始化node * **/ Node* getNode(Node *node, int value, int parent, int lChildren, int rChildren, bool isForParent, bool isTheSameWeightNode){//最后一个参数,解决这种情况,如果v1是20, //并且v1已经在树中了,然后v2也是20. //这时候要求v2要new一个新的节点。 if(node){ cout<<"getNode中,指针未初始化为NULL"<<endl; return NULL; } int pos = findNodePosViaWeight(value, isForParent, isTheSameWeightNode); if(pos != -1){ node = nodes[pos]; }else{ node = new Node(value, parent, lChildren, rChildren); } return node; } /** *把一个数组初始化为全是-1的数组。 * **/ void initArray2Zero(int *array, int length){ for(int i = 0; i < length; i++){ array[i] = -1; } } /** *打印一个int数组 */ void printIntArray(int *array, int length){ cout<<"["; for(int i = 0; i < length - 1; i++){ cout<<array[i]<<", "; } cout<<array[length - 1]<<"]"<<endl; } /** *for debug */ void debug(int i){ cout<<"debug "<<i<<endl; } /** *根据huffman树生成huffman编码。 */ char** generateHuffmanCodec(int num){ int topIndex = 0; huffmanCodec = new char*[num];//分配空间 for(int i = 0; i < num; i++){ int index = 0; char *data = new char[num + 1];//每一个节点的存储单位 int thisPos = findHuffmanNodePos(); Node *currentNode = nodes[thisPos]; while(currentNode->parent != -1){ Node *currentParent = nodes[currentNode->parent]; if(thisPos == currentParent->lChildren){//0 data[index++] = '0'; }else if(thisPos == currentParent->rChildren){//1 data[index++] = '1'; }else{//X, never in. data[index++] = 'X'; } thisPos = currentNode->parent; currentNode = currentParent; } data[index] = '\0'; huffmanCodec[topIndex++] = data; } return huffmanCodec; } public: /** *创造一棵树。 * **/ void makeTree(int num, ...){ int weightArray[num]; initArray2Zero(weightArray, num); va_list list; va_start(list, num); for(int i = 0; i < num; i++){ weightArray[i] = va_arg(list, int); } va_end(list); printIntArray(weightArray, num);//debug int debug_x = 100; while(true){ int v1 = -1, v2 = -1, v1Pos = -1, v2Pos = -1; findSmallest2ValueInArray(weightArray, num, &v1, &v2, &v1Pos, &v2Pos); if(v1 == -1 || v2 == -1){ cout<<"v1或v2至少有一个是-1, 没被赋值"<<endl; break; } Node *node1 = NULL; node1 = getNode(node1, v1, -1, -1, -1, false, false); addNode(node1);//如果已经存在就不必add。 Node *node2 = NULL; node2 = getNode(node2, v2, -1, -1, -1, false, v1 == v2);//万一v1和v2相等,如果不加这个force,那么本来有2个权值相等的节点,就会少添加到树中一个。 addNode(node2); Node *parent = NULL; parent = getNode(parent, v1 + v2, -1, -1, -1, true, false);//最后这个参数,在于判断是否是寻找的是parent。如果是parent,那么就算树中已经存在了相同节点,但是也要new一个新节点。 //因为树中的节点不是已经有了孩子 就是叶子节点了。都不能做parent了,所以要重新生成。 addNode(parent); node1->parent = findNodePosViaNode(parent); node2->parent = node1->parent; parent->lChildren = findNodePosViaNode(node1); parent->rChildren = findNodePosViaNode(node2); weightArray[v1Pos] = -1; weightArray[v2Pos] = v1 + v2; printIntArray(weightArray, num);//debug } mNum = num; generateHuffmanCodec(num); } /** *打印huffman树 * **/ void printTree(){ for(int i = 0; i < length; i++){ cout<<"pos = "<<i<<", "; nodes[i]->printNode(); //cout<<findHuffmanNodePos()<<endl; } } /** *打印哈夫曼编码 */ void printHuffman(){ cout<<"------huffman codec begin-----\n"; for(int i = 0; i < mNum; i++){ cout<<huffmanCodec[i]<<endl; } cout<<"------huffman codec end-----\n"; } /** *构造函数与析构函数 */ Tree(): nodes(new Node*[100]), huffmanCodec(NULL), length(0), rPos(-1), mNum(0){//为何是int呢?因为我想数组中存储的是Node*,是一个指针,指针应该可以用int来存储。 } ~Tree(){ cout<<"析构"<<endl; delete []nodes; if(huffmanCodec) delete []huffmanCodec; } }; int main(){ Tree *tree = new Tree; tree->makeTree(8, 5, 29, 7, 8, 14, 23, 3, 11); tree->printTree(); tree->printHuffman(); delete tree; }书上的例子才30行代码,我写了300行,为什么会这样呢,挺奇怪的,估计还是修炼不够。得努力!