Day10 树---哈夫曼树 家谱处理 搜索树判断 目录树
Posted 回忆过去,是最美好的事情。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day10 树---哈夫曼树 家谱处理 搜索树判断 目录树相关的知识,希望对你有一定的参考价值。
Huffman Codes
本题的思路是先创建哈夫曼树,求得最优WPL。之后先将待测作业的WPL计算得出,若不同于哈夫曼树的WPL必不正确;之后将待测作业编码建树来判断是否前缀冲突,若前缀冲突必不正确,反之正确。
检测编码是否冲突的核心
- 首先将所有作业中的编码按照长度递减排序
- 之后将编码建树,编码的最后一位应该落在空处;如果没有落在空处说明编码冲突。
#include<bits/stdc++.h>
#include<map>
#include<string>
#include<queue>
using namespace std;
struct Node
char val;
int weight;
Node*left=nullptr;
Node*right=nullptr;
Node()
Node(char val,int weight):val(val),weight(weight)
Node(char val,int weight,Node*left,Node*right):val(val),weight(weight),left(left),right(right)
;
//类的小根堆重载
struct cmp
bool operator()(Node*a,Node*b)
return a->weight>b->weight;
;
//创建哈夫曼树
Node* buildHuffmanTree(priority_queue<Node*,vector<Node*>,cmp>pqueue)
while(pqueue.size()>1)
Node*left=pqueue.top();pqueue.pop();
Node*right=pqueue.top();pqueue.pop();
pqueue.push(new Node(' ',left->weight+right->weight,left,right));
return pqueue.top();
int N,M;
//存储字母及频率
map<char,int>Map;
//计算哈夫曼树的WPL
void getWPL(Node*root,int&WPL,int step)
if(root==nullptr)
return;
if(root->left==nullptr&&root->right==nullptr)
WPL+=Map[root->val]*step;
getWPL(root->left,WPL,step+1);
getWPL(root->right,WPL,step+1);
//判断第二步建树是否出现问题
bool flag=true;
//建树检查编码是否冲突
Node* build(Node*root,string&code,int pos)
if(pos>=code.size())
return root;
if(pos==code.size()-1)
if((code[pos]=='0'&&root->left!=nullptr)||(code[pos]=='1'&&root->right!=nullptr))
flag=false;
return nullptr;
if(code[pos]=='0')
if(root->left==nullptr)
root->left=new Node();
root->left=build(root->left,code,pos+1);
else
if(root->right==nullptr)
root->right=new Node();
root->right=build(root->right,code,pos+1);
return root;
int main()
cin>>N;
char c;int freq;
priority_queue<Node*,vector<Node*>,cmp>pqueue;
for(int i=0;i<N;++i)
cin>>c>>freq;
Map[c]=freq;
pqueue.push(new Node(c,freq));
Node*root=buildHuffmanTree(pqueue);
int WPL=0;
getWPL(root,WPL,0);
cin>>M;
while(M--)
string code;
int cost=0;
vector<string>testCode;
flag=true;
for(int i=0;i<N;++i)
cin>>c>>code;
cost+=Map[c]*code.size();
testCode.push_back(code);
if(cost!=WPL)
cout<<"No"<<endl;
else
Node*root=new Node();
sort(testCode.begin(),testCode.end(),[](string a,string b)
return a.size()>b.size();
);
for(string code:testCode)
root=build(root,code,0);
if(!flag)
cout<<"No"<<endl;
break;
if(flag)
cout<<"Yes"<<endl;
return 0;
家谱处理
使用栈寻找父亲结点,使用map连接虚关系<子节点,父节点>
#include<bits/stdc++.h>
#include<map>
#include<stack>
using namespace std;
//子节点-->父节点
map<string,string>Map;
//结点名称 缩进
stack<pair<string,int> >S;
int N,M;
int main()
cin>>N>>M;
getchar();
string str;
string name;
while(N--)
getline(cin,str);
size_t pos=str.find_first_not_of(" ");
name=str.substr(pos);
if(S.empty())
Map[name]="null";
S.push(make_pair(name,0));
else
while(!S.empty()&&S.top().second>=pos)
S.pop();
Map[name]=S.top().first;
S.push(make_pair(name,pos));
while(M--)
string x,relation,y,temp;
cin>>x>>temp>>temp>>relation>>temp>>y;
if(relation=="child"||relation=="parent")
if(relation=="parent")
swap(x,y);
if(Map[x]==y)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
else if(relation=="ancestor"||relation=="descendant")
if(relation=="descendant")
swap(x,y);
bool flag=false;
while(Map[y]!="null")
if(x==Map[y])
flag=true;
break;
y=Map[y];
if(flag)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
else
if(Map[x]==Map[y])
cout<<"True"<<endl;
else
cout<<"False"<<endl;
return 0;
搜索树判断
本题给出二叉搜索树或者二叉镜像树的前序遍历,判断是否正确,并且给出后序遍历。
最初想的是将前序遍历排序得到中序遍历,利用前序遍历和中序遍历就可建树,不过过于麻烦,首先判断是二叉搜索树还是镜像搜索树,之后在建树的过程中还需根据树的类型查找中序遍历中根的位置。二叉搜索树的根在中序遍历为第一个大于等于根的值的位置;而二叉镜像树的根在最后一个大于等于根的值的位置。 不过最终没有满分。
现在该思路为利用先序遍历作为输入,建立二叉搜索树,求得前序遍历。二叉镜像树的前序遍历可由二叉搜索树得到,只需在前序遍历时先访问右子结点。相同方法得到后序遍历。判断输入遍历是否为二叉搜索树或二叉镜像树遍历的一种,之后输出后序遍历即可。
#include<bits/stdc++.h>
#include<vector>
using namespace std;
vector<int>originalPre;
vector<int>pre,preMirror,post,postMirror;
struct Node
int val;
Node*left=nullptr;
Node*right=nullptr;
Node()
Node(int val):val(val)
Node(int val,Node*left,Node*right):val(val),left(left),right(right)
;
Node* insert(Node*root,int newVal)
if(root==nullptr)
root=new Node(newVal);
else if(newVal<root->val)
root->left=insert(root->left,newVal);
else
root->right=insert(root->right,newVal);
return root;
void preOrder(Node*root)
if(root==nullptr)
return;
pre.push_back(root->val);
preOrder(root->left);
preOrder(root->right);
void preMirrorOrder(Node*root)
if(root==nullptr)
return;
preMirror.push_back(root->val);
preMirrorOrder(root->right);
preMirrorOrder(root->left);
void postOrder(Node*root)
if(root==nullptr)
return;
postOrder(root->left);
postOrder(root->right);
post.push_back(root->val);
void postMirrorOrder(Node*root)
if(root==nullptr)
return;
postMirrorOrder(root->right);
postMirrorOrder(root->left);
postMirror.push_back(root->val);
int main()
int N;
int val;
Node*root=nullptr;
cin>>N;
for(int i=0; i<N; ++i)
cin>>val;
originalPre.push_back(val);
root=insert(root,val);
preOrder(root);
preMirrorOrder(root);
postOrder(root);
postMirrorOrder(root);
//二叉搜索树的先序遍历
if(originalPre==pre)
cout<<"YES"<<endl;
cout<<post[0];
for(int i=1;i<post.size();++i)
cout<<" "<<post[i];
cout<<endl;
else if(originalPre==preMirror)
cout<<"YES"<<endl;
cout<<postMirror[0];
for(int i=1;i<postMirror.size();++i)
cout<<" "<<postMirror[i];
cout<<endl;
else
cout<<"NO"<<endl;
return 0;
目录树
根据目录归档文件重建目录树,需要注意的是目录需要在文件之前打印,需要在Node中设置一个表示isFolder来记录。递归建树,递归打印。
#include<bits/stdc++.h>
#include<map>
using namespace std;
struct Node
//结点名称
string name;
//子节点名称,地址,递归使用
map<string,Node*>subFiles;
//判断该节点是否为文件夹
bool isFolder;
Node()
Node(string name):name(name)
Node(string name,bool isFolder):name(name),isFolder(isFolder)
;
//加文件
Node* add(Node*root,string file)
if(file.find("\\\\")==string::npos) //文件
if(root->subFiles.find(file)==root->subFiles.end())//文件已存在不需重新创建
root->subFiles[file]=new Node(file,false);
else if(file.find("\\\\")==file.size()-1) //目录文件
if(root->subFiles.find(file.substr(0,file.size()-1))==root->subFiles.end())//目录已存在,不需重新创建
root->subFiles[file.substr(0,file.size()-1)]=new Node(file.substr(0,file.size()-1),true);
else //多级目录
size_t pos=file.find_first_of("\\\\");
string firstDir=file.substr(0,pos);
//目录不存在直接创建
if(root->subFiles.find(firstDir)==root->subFiles.end())
root->subFiles[firstDir]=new Node(firstDir,true);
root->subFiles[firstDir]=add(root->subFiles[firstDir],file.substr(pos+1));
return root;
void dfs(Node*root,int depth)
if(root==nullptr)
return;
for(int i=0; i<depth; ++i)
cout<<" ";
cout<<root->name<<endl;
vector<Node*>subFiles;
for(auto it:root->subFiles)
subFiles.push_back(it.second);
sort(subFiles.begin(),subFiles.end(),[](Node*a,Node*b)
//同为文件或者目录
if(a->isFolder&&b->isFolder||!a->isFolder&&!b->isFolder)
return a->name<b->name;
else
return a->isFolder;
);
for(Node*subFile:subFiles)
dfs(subFile,depth+2);
int main()
Node*root=new Node("root",true);
int N;
cin>>N;
string file;
for(int i=0; i<N; ++i)
cin>>file;
root=add(root,file);
dfs(root,0);
return 0;
以上是关于Day10 树---哈夫曼树 家谱处理 搜索树判断 目录树的主要内容,如果未能解决你的问题,请参考以下文章