C++ Can';t编写一个用于构建哈夫曼树的函数
我得到了一个C++ Can';t编写一个用于构建哈夫曼树的函数,c++,algorithm,binary-tree,huffman-code,C++,Algorithm,Binary Tree,Huffman Code,我得到了一个struct元素,其中包含关于树元素的信息 struct element { char ch; //Letter int left; //Number in array int right; //Number in arry int count; //Count letter in word }; 另外,我还有一个函数MakeAlphabet,它为std::string生成字母表: std::vector<element> Make
struct元素
,其中包含关于树元素的信息
struct element
{
char ch; //Letter
int left; //Number in array
int right; //Number in arry
int count; //Count letter in word
};
另外,我还有一个函数MakeAlphabet
,它为std::string
生成字母表:
std::vector<element> MakeAlphabet(std::string str) //РАБОТАЕТ!
{
std::vector<element> alphabet;
ranges::sort(str);
for(auto ch : str | ranges::views::unique)
{
alphabet.push_back(element{ch, -1, -1, static_cast<int>(ranges::count(str, ch))});
}
return alphabet;
};
当检查结果树的根(它必须与单词中的字母数匹配)时,结果几乎总是不正确的
UPD:
我有std::sort(alphabet.begin(),alphabet.end())的重载操作符代码>
bool操作符必须对数组进行排序,取出现次数最少的两个节点形成一个新节点,将其放回数组中。数组将再次排序,以此类推。。。
因此,它只有一个数组,即字母
使用指向元素(element*)的指针,而不是只指向元素,因为很容易将它们从数组切换到树。
创建一个节点类
class node{
};
class inner_node: public node
{
node *left, *right;
int count; //Count letter in word
};
class element: public node
{
public:
char ch; //Letter
int count; //Count letter in word
};
std::vector<node*> MakeAlphabet(std::string str) //РАБОТАЕТ!
{
std::vector<node*> alphabet;
ranges::sort(str);
for(auto ch : str | ranges::views::unique)
{
element *e = new element();
e->ch = ch;
e->static_cast<int>(ranges::count(str, ch));
alphabet.push_back(e);
}
return alphabet;
}
std::vector<node*> MakeBinaryTree(std::string str)
{
std::vector<node*> alphabet = MakeAlphabet(str);
// keep going until there is only the huffman tree root left in the vector
while(alphabet.size() > 1)
{
std::sort(alphabet.begin(), alphabet.end());
// Takes last two elements and remove them
inner_node *first = (inner_node*) alphabet.back();
alphabet.pop_back();
inner_node *second = (inner_node*) alphabet.back();
alphabet.pop_back();
// Creates tree node and put in the vector
inner_node *n = new node();
n->left = first;
n->right = second;
n->count = first->count + second->count;
alphabet.push_back(n);
}
return alphabet;
}
类节点{
};
类内部节点:公共节点
{
节点*左,*右;
int count;//计算单词中的字母
};
类元素:公共节点
{
公众:
char ch;//字母
int count;//计算单词中的字母
};
std::vector MakeAlphabet(std::string str)//ПАБССАСАС!
{
向量字母表;
范围::排序(str);
用于(自动ch:str |范围::视图::唯一)
{
元素*e=新元素();
e->ch=ch;
e->static_cast(范围::count(str,ch));
字母表。推回(e);
}
返回字母表;
}
std::vector MakeBinaryTree(std::string str)
{
std::vector alphabet=MakeAlphabet(str);
//继续,直到向量中只剩下哈夫曼树根
while(alphabet.size()>1)
{
排序(alphabet.begin(),alphabet.end());
//获取最后两个元素并删除它们
内部节点*first=(内部节点*)字母表.back();
字母表;
内部节点*秒=(内部节点*)字母表.back();
字母表;
//创建树节点并放入向量中
内部节点*n=新节点();
n->左=第一;
n->右=秒;
n->计数=第一->计数+第二->计数;
字母表。推回(n);
}
返回字母表;
}
必须对数组进行排序,取出现次数最少的两个节点形成一个新节点,并将其放回数组中。数组将再次排序,以此类推。。。
因此,它只有一个数组,即字母
使用指向元素(element*)的指针,而不是只指向元素,因为很容易将它们从数组切换到树。
创建一个节点类
class node{
};
class inner_node: public node
{
node *left, *right;
int count; //Count letter in word
};
class element: public node
{
public:
char ch; //Letter
int count; //Count letter in word
};
std::vector<node*> MakeAlphabet(std::string str) //РАБОТАЕТ!
{
std::vector<node*> alphabet;
ranges::sort(str);
for(auto ch : str | ranges::views::unique)
{
element *e = new element();
e->ch = ch;
e->static_cast<int>(ranges::count(str, ch));
alphabet.push_back(e);
}
return alphabet;
}
std::vector<node*> MakeBinaryTree(std::string str)
{
std::vector<node*> alphabet = MakeAlphabet(str);
// keep going until there is only the huffman tree root left in the vector
while(alphabet.size() > 1)
{
std::sort(alphabet.begin(), alphabet.end());
// Takes last two elements and remove them
inner_node *first = (inner_node*) alphabet.back();
alphabet.pop_back();
inner_node *second = (inner_node*) alphabet.back();
alphabet.pop_back();
// Creates tree node and put in the vector
inner_node *n = new node();
n->left = first;
n->right = second;
n->count = first->count + second->count;
alphabet.push_back(n);
}
return alphabet;
}
类节点{
};
类内部节点:公共节点
{
节点*左,*右;
int count;//计算单词中的字母
};
类元素:公共节点
{
公众:
char ch;//字母
int count;//计算单词中的字母
};
std::vector MakeAlphabet(std::string str)//ПАБССАСАС!
{
向量字母表;
范围::排序(str);
用于(自动ch:str |范围::视图::唯一)
{
元素*e=新元素();
e->ch=ch;
e->static_cast(范围::count(str,ch));
字母表。推回(e);
}
返回字母表;
}
std::vector MakeBinaryTree(std::string str)
{
std::vector alphabet=MakeAlphabet(str);
//继续,直到向量中只剩下哈夫曼树根
while(alphabet.size()>1)
{
排序(alphabet.begin(),alphabet.end());
//获取最后两个元素并删除它们
内部节点*first=(内部节点*)字母表.back();
字母表;
内部节点*秒=(内部节点*)字母表.back();
字母表;
//创建树节点并放入向量中
内部节点*n=新节点();
n->左=第一;
n->右=秒;
n->计数=第一->计数+第二->计数;
字母表。推回(n);
}
返回字母表;
}
使用优先级队列而不是向量
如果你想的话,可以进行一次哈夫曼编码
我使用优先级队列
重新实现了MakeBinaryTree
函数
其他一切都是一样的
示例案例:-
character Frequency
a 5
b 9
c 12
d 13
e 16
f 45
预期结果:-
std::vector中的最终输出:
表示内部节点
工作代码:-
#include <iostream>
#include <vector>
#include <utility>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <string_view>
#include <deque>
#include <array>
#include <algorithm>
#include <range/v3/algorithm/count.hpp>
#include <range/v3/action/sort.hpp>
#include <range/v3/view/unique.hpp>
#include <exception>
#include <gtest/gtest.h>
struct element //Элемент бинарного дерева.
{
char ch;
struct element* left;
struct element* right;
int count;
};
bool operator<(const element &first, const element &second)
{
return (first.count > second.count); // Reversed to form min heap instead of default max heap
}
bool operator==(const element &first, const element &second)
{
return (first.count == second.count);
}
std::vector<element> MakeAlphabet(std::string str) //РАБОТАЕТ!
{
std::vector<element> alphabet;
ranges::sort(str);
for(auto ch : str | ranges::views::unique)
{
alphabet.push_back(element{ch, NULL, NULL, static_cast<int>(ranges::count(str, ch))});
}
return alphabet;
};
std::vector<element> MakeBinaryTree(std::string str) //НЕ работает.
{
std::vector<element> result;
std::vector<element> alphabet = MakeAlphabet(str);
std::priority_queue<element> min_heap;
//Initialize Min Heap
for(auto x:alphabet)
min_heap.push(x);
// Form Huffman Encoding Tree
while(min_heap.size()>1){
element *lc = (element*)malloc(sizeof(element));*lc=min_heap.top();min_heap.pop();
element *rc = (element*)malloc(sizeof(element));*rc=min_heap.top();min_heap.pop();
min_heap.push(element{'.',lc,rc,lc->count + rc->count});
}
std::queue<element> prefix_traversal;
prefix_traversal.push(min_heap.top());
// Convert Tree to Vector using BFS
while(prefix_traversal.size()>0){
element top = prefix_traversal.front();
prefix_traversal.pop();
result.push_back(top);
if(top.left != NULL)
prefix_traversal.push(*top.left);
if(top.right != NULL)
prefix_traversal.push(*top.right);
}
return result;
};
int main(){
std::string s;
for(int i=0;i<13;i+=1)s+="d";
for(int i=0;i<9;i+=1)s+="b";
for(int i=0;i<5;i+=1)s+="a";
for(int i=0;i<12;i+=1)s+="c";
for(int i=0;i<16;i+=1)s+="e";
for(int i=0;i<45;i+=1)s+="f";
std::vector<element> result = MakeBinaryTree(s);
printf("Index \tCharacter\tFrequency\n");
for(int i=0;i<result.size(); i+=1){
// std::cout<<"Index "<<i<<" "<<result[i].ch<<" "<<result[i].count<<std::endl;
printf("%4d\t\t%3c\t\t%4d\n",i,result[i].ch,result[i].count);
}
return 1;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构元素//ББМБббаааааааааааа。
{
char ch;
结构元素*左;
结构元素*右;
整数计数;
};
布尔运算符秒。计数);//反转以形成最小堆而不是默认最大堆
}
布尔运算符==(常量元素和第一个、常量元素和第二个)
{
返回(first.count==second.count);
}
std::vector MakeAlphabet(std::string str)//ПАБССАСАС!
{
向量字母表;
范围::排序(str);
用于(自动ch:str |范围::视图::唯一)
{
字母表。推回(元素{ch,NULL,NULL,static_cast(ranges::count(str,ch))});
}
返回字母表;
};
std::vector MakeBinaryTree(std::string str)//。
{
std::向量结果;
std::vector alphabet=MakeAlphabet(str);
std::优先级队列最小堆;
//初始化最小堆
用于(自动x:字母表)
最小堆压(x);
//表单哈夫曼编码树
while(min_heap.size()>1){
element*lc=(element*)malloc(sizeof(element));*lc=min_heap.top();min_heap.pop();
element*rc=(element*)malloc(sizeof(element));*rc=min_heap.top();min_heap.pop();
min_heap.push(元素{'.',lc,rc,lc->count+rc->count});
}
std::队列前缀遍历;
前缀_traversal.push(min_heap.top());
//使用BFS将树转换为向量
while(前缀_traversal.size()>0){
元素top=前缀_traversal.front();
前缀_traversal.pop();
结果:推回(顶部);
if(左上角!=NULL)
前缀_traversal.p
Index Character Frequency
0 . 100
1 f 45
2 . 55
3 . 25
4 . 30
5 c 12
6 d 13
7 . 14
8 e 16
9 a 5
10 b 9
#include <iostream>
#include <vector>
#include <utility>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <string_view>
#include <deque>
#include <array>
#include <algorithm>
#include <range/v3/algorithm/count.hpp>
#include <range/v3/action/sort.hpp>
#include <range/v3/view/unique.hpp>
#include <exception>
#include <gtest/gtest.h>
struct element //Элемент бинарного дерева.
{
char ch;
struct element* left;
struct element* right;
int count;
};
bool operator<(const element &first, const element &second)
{
return (first.count > second.count); // Reversed to form min heap instead of default max heap
}
bool operator==(const element &first, const element &second)
{
return (first.count == second.count);
}
std::vector<element> MakeAlphabet(std::string str) //РАБОТАЕТ!
{
std::vector<element> alphabet;
ranges::sort(str);
for(auto ch : str | ranges::views::unique)
{
alphabet.push_back(element{ch, NULL, NULL, static_cast<int>(ranges::count(str, ch))});
}
return alphabet;
};
std::vector<element> MakeBinaryTree(std::string str) //НЕ работает.
{
std::vector<element> result;
std::vector<element> alphabet = MakeAlphabet(str);
std::priority_queue<element> min_heap;
//Initialize Min Heap
for(auto x:alphabet)
min_heap.push(x);
// Form Huffman Encoding Tree
while(min_heap.size()>1){
element *lc = (element*)malloc(sizeof(element));*lc=min_heap.top();min_heap.pop();
element *rc = (element*)malloc(sizeof(element));*rc=min_heap.top();min_heap.pop();
min_heap.push(element{'.',lc,rc,lc->count + rc->count});
}
std::queue<element> prefix_traversal;
prefix_traversal.push(min_heap.top());
// Convert Tree to Vector using BFS
while(prefix_traversal.size()>0){
element top = prefix_traversal.front();
prefix_traversal.pop();
result.push_back(top);
if(top.left != NULL)
prefix_traversal.push(*top.left);
if(top.right != NULL)
prefix_traversal.push(*top.right);
}
return result;
};
int main(){
std::string s;
for(int i=0;i<13;i+=1)s+="d";
for(int i=0;i<9;i+=1)s+="b";
for(int i=0;i<5;i+=1)s+="a";
for(int i=0;i<12;i+=1)s+="c";
for(int i=0;i<16;i+=1)s+="e";
for(int i=0;i<45;i+=1)s+="f";
std::vector<element> result = MakeBinaryTree(s);
printf("Index \tCharacter\tFrequency\n");
for(int i=0;i<result.size(); i+=1){
// std::cout<<"Index "<<i<<" "<<result[i].ch<<" "<<result[i].count<<std::endl;
printf("%4d\t\t%3c\t\t%4d\n",i,result[i].ch,result[i].count);
}
return 1;
}