霍夫曼编码器-递归,编码功能失败
Huffman Encoder - Recursive, coding function fail
我正在开发一个霍夫曼代码生成器。下面是我制作这棵树的功能。该树基于对象指针的矢量。我检查过了,它似乎工作正常。我现在想将指针在pointerVect[0]的位置(它应该是树的根)传递给下面的霍夫曼编码递归函数,但由于某种原因,它无法正常工作,因为当我试图打印存储代码的映射的内容时,没有打印出任何内容。
class asciiChar //Individual character module >>> Base Class
{
public:
void setCharValue (char letter)
{
charValue = letter;
}
char getCharValue ()
{
return charValue;
}
void incrementCharCount ()
{
charCount++;
}
int getCharCount()
{
return charCount;
}
virtual asciiChar * getLeft()
{
return left;
}
virtual asciiChar * getRight()
{
return right;
}
asciiChar(char c, int f) //Constructor
{
charValue = c;
charCount = f;
}
asciiChar & operator= (const asciiChar & other) //Overloaded assignment operator
{
charValue = other.charValue;
charCount = other.charCount;
return *this;
}
char charValue;
int charCount = 0;
asciiChar * left = NULL;
asciiChar * right = NULL;
};
class parentNode : public asciiChar //Connector node
{
public:
parentNode(asciiChar c0, asciiChar c1) : asciiChar(NULL, c0.getCharCount() + c1.getCharCount())
{
left = &c0;
right = &c1;
}
~parentNode()
{
if (left) delete left;
if (right) delete right;
}
};
asciiChar* createTree (vector<asciiChar> sortedVector)
{
vector<asciiChar*> pointerVect;
pointerVect.reserve(sortedVector.size());
for(int i=0; i < sortedVector.size(); i++)
{
pointerVect.push_back(new asciiChar(sortedVector[i].getCharValue(), sortedVector[i].getCharCount()));
}
while (pointerVect.size() > 1)
{
asciiChar * newL = pointerVect.back();
pointerVect.pop_back();
asciiChar * newR = pointerVect.back();
pointerVect.pop_back();
asciiChar * parent = new parentNode(* newL, * newR);
pointerVect.push_back(parent);
vectSort2 (pointerVect);
}
return pointerVect[0]; //Returns pointer at very top (The root of the tree)
}
我怀疑你的第一个函数是"createTree"
正如我最初的评论所指出的,出于各种原因,您应该考虑使用优先级队列。以下是我注意到的问题的快速列表
- 您正在对指针向量进行排序。因此,指针将根据它们的地址值而不是它们所指向的对象进行排序。但是,您可能正在提供一个比较器。如果是这种情况,请忽略此项目符号
- 每次循环迭代时解析向量为O(nLog(n)),其中插入优先级队列并保持排序顺序为O(Log(n)
- 由于您对指针进行排序,因此向量的索引0不能保证是树的根
请考虑使用优先级队列:在头文件中
#include <queue>
// Comparator for priority queue. Use this so it compared what the pointers point too and not the pointers themselves. This way the frequencies are used for the
// comparisons. This forces the priority queue to order from lowest freq
// to the highest frequency
struct CompareHuffChars : public binary_function<asciiChar*, asciiChar*, bool>
{
bool operator()(const asciiChar* left, const asciiChar* right) const
{
// Be sure to add functionality to get frequency for each asciiChar object
return left->getFrequency() > right->getFrequency();
}
}; // end struct
priority_queue<asciiChar*,vector<asciiChar*>,CompareHuffChars > * bytePriorityQueue;
asciiChar * huffmanTree; // Pointer to assign to root node of tree when found
在实现文件中。。。。
while (!(this->bytePriorityQueue->empty())) {
asciiChar * qtop = this->bytePriorityQueue->top();
this->bytePriorityQueue->pop();
if (this->bytePriorityQueue->empty()) {
// Found the root asciiChar node
this->huffmanTree = qtop; // huffManTree = asciiChar *
} else {
// There are more asciiChar nodes so we need to grab the 2nd from top
// and combine their frequencies into a new asciiChar node and insert it
// back into the priority queue
asciiChar * newNode;
asciiCharChar * qtopSecond = this->bytePriorityQueue->top();
// Remove it from the queue
this->bytePriorityQueue->pop();
// Now create a new asciiChar node with the added frequences
// qtopSecond should always be > or = qtop
// which will adhere to the binary tree structure
// This assumes asciiChar adds the frequencies of qtop and qtopSecond in constructor
newNode = new asciiChar(qtop,qtopSecond);
// Push the new node into the p queue
// Stays sorted with Log(n) insertion
this->bytePriorityQueue->push(newNode);
// Now repeat this until the tree is formed (1 node left in queue)
} // end if
} // end while
//The p queue should now be completely empty (len =0)
}
现在,我的版本需要对asciiChar进行一点重构。但是,这种方法应该比发布的方法更好,并解决您的错误。
编辑
好吧,我想我已经发现了你的错误。在asciiChar的头文件中,getLeft和getRight函数是非虚拟函数。这意味着,当您有一个asciiChar*类型的基指针指向parentNode(子类)类型的对象时,它将调用父对象(asciiChar)的getLeft和getRight函数,该函数将始终返回NULL。您在子类(parentNode)中重新声明了一个left和right,因为这些成员变量在父类中是公共的,所以不需要这样做。使getLeft和getRight函数成为虚拟函数,并删除parentNode类中left和right的声明以及它们各自的getter函数。
// In aschiiChar
virtual asciiChar * getLeft()
{
return left;
}
virtual asciiChar * getRight()
{
return right;
}
旁注:在删除之前,如果指针为NULL,则应检查析构函数。
if (left) delete left;
if (right) delete right;
最终编辑
感谢您发布更多信息。好吧,你的问题归结为以下几点:
// This is your parentNode constructor
parentNode(asciiChar c0, asciiChar c1) : asciiChar(NULL, c0.getCharCount() + c1.getCharCount())
{
left = &c0;
right = &c1;
}
// This is what the parentNode constructor should look like
parentNode(asciiChar * c0, asciiChar * c1) : asciiChar(NULL, c0->getCharCount() + c1->getCharCount())
{
left = c0;
right = c1;
}
最后。。。
asciiChar* createTree (vector<asciiChar> sortedVector)
{
vector<asciiChar*> pointerVect;
pointerVect.reserve(sortedVector.size());
for(int i=0; i < sortedVector.size(); i++)
{
pointerVect.push_back(new asciiChar(sortedVector[i].getCharValue(), sortedVector[i].getCharCount()));
}
while (pointerVect.size() > 1)
{
asciiChar * newL = pointerVect.back();
pointerVect.pop_back();
asciiChar * newR = pointerVect.back();
pointerVect.pop_back();
// CHANGE HERE
// Don't dereference the pointers. If you dereference them you are passing by value
// and creating copies in the constructor which are destroyed upon exit of the constructor
asciiChar * parent = new parentNode( newL, newR);
pointerVect.push_back(parent);
vectSort2 (pointerVect);
}
return pointerVect[0]; //Returns pointer at very top (The root of the tree)
}
您的问题归结为传递值并将本地副本的地址分配给parentNode的成员变量指针。parentNode中的这些指针指向不存在的内存或不属于它们的内存。
希望这能帮助。。。
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 多态性和功能结合
- 如何确定我已使用非编码文件到达 EOF?
- 带内存和隔离功能的SQLite
- 在CMakeLists.txt的安装功能中使用.cmake文件有什么用
- 类模板的成员功能的定义在单独的TU中完全专业化
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在C++中获得"静态纯虚拟"功能?
- 两个文件使用彼此的功能-如何解决
- 我应该实现右值推送功能吗?我应该使用std::move吗
- QML按钮点击功能执行顺序
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 有没有可能有一个只有ADL才能找到的非好友功能
- 功能样式转换从 'int' 到 'ItemType' 的匹配转换
- 文件系统:复制功能的速度秘诀是什么
- 为什么这个base64解码/编码功能不能正常工作?
- 如何编码和超载返回自身的功能?C 17
- FFmpeg音频编码器新增编码功能
- 霍夫曼编码器-递归,编码功能失败