Day10 树---哈夫曼树 家谱处理 搜索树判断 目录树

Huffman Codes

本题的思路是先创建哈夫曼树,求得最优WPL。之后先将待测作业的WPL计算得出,若不同于哈夫曼树的WPL必不正确;之后将待测作业编码建树来判断是否前缀冲突,若前缀冲突必不正确,反之正确。
检测编码是否冲突的核心

  • 首先将所有作业中的编码按照长度递减排序
  • 之后将编码建树,编码的最后一位应该落在空处;如果没有落在空处说明编码冲突。
#include
#include
#include
#include
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,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;
//存储字母及频率 
mapMap;
//计算哈夫曼树的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,cmp>pqueue;
	for(int i=0;i>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;
		vectortestCode;
		flag=true; 
		for(int i=0;i>c>>code;
			cost+=Map[c]*code.size();
			testCode.push_back(code); 
		}
		if(cost!=WPL){
			cout<<"No"<b.size();
			});
			for(string code:testCode){
				root=build(root,code,0);
				if(!flag){
					cout<<"No"<

家谱处理

使用寻找父亲结点,使用map连接虚关系<子节点,父节点>

#include 
#include
#include
using namespace std;
//子节点-->父节点 
mapMap;
//结点名称 缩进 
stack >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"<

搜索树判断

本题给出二叉搜索树或者二叉镜像树的前序遍历,判断是否正确,并且给出后序遍历。

最初想的是将前序遍历排序得到中序遍历,利用前序遍历和中序遍历就可建树,不过过于麻烦,首先判断是二叉搜索树还是镜像搜索树,之后在建树的过程中还需根据树的类型查找中序遍历中根的位置。二叉搜索树的根在中序遍历为第一个大于等于根的值的位置;而二叉镜像树的根在最后一个大于等于根的值的位置。 不过最终没有满分。
现在该思路为利用先序遍历作为输入,建立二叉搜索树,求得前序遍历。二叉镜像树的前序遍历可由二叉搜索树得到,只需在前序遍历时先访问右子结点。相同方法得到后序遍历。判断输入遍历是否为二叉搜索树或二叉镜像树遍历的一种,之后输出后序遍历即可。

#include
#include
using namespace std;
vectororiginalPre;
vectorpre,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(newValval) {
		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>val;
		originalPre.push_back(val);
		root=insert(root,val);
	}
	preOrder(root);
	preMirrorOrder(root);
	postOrder(root);
	postMirrorOrder(root);
	//二叉搜索树的先序遍历 
	if(originalPre==pre){
		cout<<"YES"<

目录树

根据目录归档文件重建目录树,需要注意的是目录需要在文件之前打印,需要在Node中设置一个表示isFolder来记录。递归建树,递归打印。

#include
#include
using namespace std;
struct Node {
	//结点名称 
	string name;
	//子节点名称,地址,递归使用
	mapsubFiles;
	//判断该节点是否为文件夹 
	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; iname<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->namename; 
		}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>file;
		root=add(root,file);
	}
	dfs(root,0);
	return 0;
}

你可能感兴趣的:(刷题,leetcode,哈夫曼树)