不知道为什么,我写的代码都是又臭又长。
直接上代码:
#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行,为什么会这样呢,挺奇怪的,估计还是修炼不够。得努力!