题目描述:一个关于三叉树的题目,小于100的值代表树叶,大于100的值为分支点,建树的过程是水平方向建树,输入格式:
先输入n,代表有n组数据,接下来n行,输入4个数,第一个数代表根节点,接下来分别代表三个子节点,-1代表子节点不存在,输入的顺序按照层次遍历的次序。接下来,要求寻找叶子节点的最短路径,最短路径是指不经过重复的边。输入方式,首先输入一个值m,代表m行,接下来m行输入m个叶子节点和对应的优先级,要求按优先级输出从上次到达的位置到该节点的最短路径,每条路径的最后一个节点要求输出目标叶子节点,最后要求回到根节点。
示例输入:10
100 101 108 107
101 1 102 2
108 103 104 105
107 17 109 18
102 3 4 5
103 7 8 9
104 10 106 11
105 15 16 -1
109 19 20 21
106 12 13 14
5
8 1
14 3
16 2
5 0
19 4
样例输出:100 101 102 5
102 101 100 108 103 8
103 108 105 16
105 108 104 106 14
106 104 108 100 107 109 19
109 107 100
这是建立的树:
思路解析:
第一步肯定是建树,声明数据结构,利用队列建树
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
struct triTree{
int data;
struct triTree *lchild;
struct triTree *mchild;
struct triTree *rchild;
struct triTree *parent;
triTree()
{
lchild = NULL;
mchild = NULL;
rchild = NULL;
parent = NULL;
}
triTree(int x)
{
data = x;
lchild = NULL;
mchild = NULL;
rchild = NULL;
parent = NULL;
}
};
queue<triTree*> q;
triTree* createTree(triTree* root,int rt,int a,int b,int c)
{
if(root->parent==NULL)
{
root->data= rt;
}
if(a!=-1){
triTree *newNode = new triTree(a);
root->lchild = newNode;
newNode->parent = root;
if(newNode->data>=100) q.push(newNode);
}else root->lchild = NULL;
if(b!=-1){
triTree *newNode = new triTree(b);
root->mchild = newNode;
newNode->parent = root;
if(newNode->data>=100) q.push(newNode);
}else root->mchild = NULL;
if(c!=-1){
triTree *newNode = new triTree(c);
root->rchild = newNode;
newNode->parent = root;
if(newNode->data>=100) q.push(newNode);
}else root->rchild = NULL;
if(!q.empty()){
triTree* tmp = q.front();
q.pop();
return tmp;
}else return NULL;
}
//void pre_test(triTree* test)
//{
// if(test==NULL) return;
// cout<<test->data<<" ";
// pre_test(test->lchild);
// pre_test(test->mchild);
// pre_test(test->rchild);
//}
int main()
{
freopen("in.txt","r",stdin);
int n;
cin>>n;
int rt,a,b,c;
struct triTree* root = new triTree;
struct triTree* tmp = root;
for(int i=0;i<n;i++)
{
cin>>rt>>a>>b>>c;
tmp = createTree(tmp,rt,a,b,c);
}
//pre_test(root);
}
第二步处理下一组输入,并且排序
struct target{
int target;
int priority;
bool operator<( const struct target& t)const
{
return priority<t.priority;
}
};
int m;
cin>>m;
target t[m];
for(int i=0;i<m;i++)
{
cin>>t[i].target>>t[i].priority;
}
sort(t,t+m);
第三步,需要四个函数,需要从输入的节点值获取在树中的节点地址(指针),根据两个节点后序遍历求最近的公共父节点,
从公共节点出发前序遍历找到目标路径的节点和打印函数。
struct triTree* search_node(triTree* root,int x)
{
if(root==NULL||root->data==x) return root;
struct triTree* tmp = search_node(root->lchild,x);
if(tmp!=NULL) return tmp;
else tmp = search_node(root->mchild,x);
if(tmp!=NULL) return tmp;
else tmp = search_node(root->rchild,x);
if(tmp!=NULL) return tmp;
else return NULL;
}
struct triTree* getNearestRoot(triTree* root,triTree* node1,triTree *node2)
{
if(root==NULL||root==node1||root==node2) return root;
triTree* left = getNearestRoot(root->lchild,node1,node2);
triTree* middle = getNearestRoot(root->mchild,node1,node2);
triTree* right = getNearestRoot(root->rchild,node1,node2);
if(left!=NULL&&middle!=NULL) return root;
if(left!=NULL&&right!=NULL) return root;
if(middle!=NULL&&right!=NULL) return root;
if(left!=NULL) return left;
if(middle!=NULL) return middle;
if(right!=NULL) return right;
return NULL;
}
vector<int> result;
triTree* preOrder(triTree* root,int x)
{
if(root==NULL||root->data==x) return root;
result.push_back(root->data);
triTree* tmp = preOrder(root->lchild,x);
if(root->lchild==NULL);
else if(tmp==NULL||tmp->data!=x) result.pop_back();
else return tmp;
tmp = preOrder(root->mchild,x);
if(root->mchild==NULL);
else if(tmp==NULL||tmp->data!=x) result.pop_back();
else return tmp;
tmp = preOrder(root->rchild,x);
if(root->rchild==NULL);
else if(tmp==NULL||tmp->data!=x) result.pop_back();
else return tmp;
}
void print()
{
int len = result.size();
for(int i=0;i<len;i++)
{
cout<<result[i]<<" ";
}
}
第四步:按照输出格式进行输出即可
triTree *tmp1 = root;
triTree *tmp2,*troot;
triTree *last = root;
for(int i=0;i<m;i++)
{
result.clear();
tmp2 = search_node(root,t[i].target);
troot = getNearestRoot(root,tmp1,tmp2);
while(last!=troot)
{
result.push_back(last->data);
last = last->parent;
}
preOrder(troot,t[i].target);
print();
cout<<tmp2->data<<" "<<endl;
tmp1 = tmp2;
last = search_node(root,result.back());
}
while(last!=NULL)
{
cout<<last->data<<" ";
last = last->parent;
}
cout<<endl;
这里给出全部代码(注释掉的代码是为了调试,无意义)
#include<iostream>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
struct triTree{
int data;
struct triTree *lchild;
struct triTree *mchild;
struct triTree *rchild;
struct triTree *parent;
triTree()
{
lchild = NULL;
mchild = NULL;
rchild = NULL;
parent = NULL;
}
triTree(int x)
{
data = x;
lchild = NULL;
mchild = NULL;
rchild = NULL;
parent = NULL;
}
};
queue<triTree*> q;
vector<int> result;
triTree* createTree(triTree* root,int rt,int a,int b,int c)
{
if(root->parent==NULL)
{
root->data= rt;
}
if(a!=-1){
triTree *newNode = new triTree(a);
root->lchild = newNode;
newNode->parent = root;
if(newNode->data>=100) q.push(newNode);
}else root->lchild = NULL;
if(b!=-1){
triTree *newNode = new triTree(b);
root->mchild = newNode;
newNode->parent = root;
if(newNode->data>=100) q.push(newNode);
}else root->mchild = NULL;
if(c!=-1){
triTree *newNode = new triTree(c);
root->rchild = newNode;
newNode->parent = root;
if(newNode->data>=100) q.push(newNode);
}else root->rchild = NULL;
if(!q.empty()){
triTree* tmp = q.front();
q.pop();
return tmp;
}else return NULL;
}
//void pre_test(triTree* test)
//{
// if(test==NULL) return;
// cout<<test->data<<" ";
// pre_test(test->lchild);
// pre_test(test->mchild);
// pre_test(test->rchild);
//}
struct target{
int target;
int priority;
bool operator<( const struct target& t)const
{
return priority<t.priority;
}
};
struct triTree* search_node(triTree* root,int x)
{
if(root==NULL||root->data==x) return root;
struct triTree* tmp = search_node(root->lchild,x);
if(tmp!=NULL) return tmp;
else tmp = search_node(root->mchild,x);
if(tmp!=NULL) return tmp;
else tmp = search_node(root->rchild,x);
if(tmp!=NULL) return tmp;
else return NULL;
}
struct triTree* getNearestRoot(triTree* root,triTree* node1,triTree *node2)
{
if(root==NULL||root==node1||root==node2) return root;
triTree* left = getNearestRoot(root->lchild,node1,node2);
triTree* middle = getNearestRoot(root->mchild,node1,node2);
triTree* right = getNearestRoot(root->rchild,node1,node2);
if(left!=NULL&&middle!=NULL) return root;
if(left!=NULL&&right!=NULL) return root;
if(middle!=NULL&&right!=NULL) return root;
if(left!=NULL) return left;
if(middle!=NULL) return middle;
if(right!=NULL) return right;
return NULL;
}
void print()
{
int len = result.size();
for(int i=0;i<len;i++)
{
cout<<result[i]<<" ";
}
}
triTree* preOrder(triTree* root,int x)
{
if(root==NULL||root->data==x) return root;
result.push_back(root->data);
triTree* tmp = preOrder(root->lchild,x);
if(root->lchild==NULL);
else if(tmp==NULL||tmp->data!=x) result.pop_back();
else return tmp;
tmp = preOrder(root->mchild,x);
if(root->mchild==NULL);
else if(tmp==NULL||tmp->data!=x) result.pop_back();
else return tmp;
tmp = preOrder(root->rchild,x);
if(root->rchild==NULL);
else if(tmp==NULL||tmp->data!=x) result.pop_back();
else return tmp;
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
cin>>n;
int rt,a,b,c;
struct triTree* root = new triTree;
struct triTree* tmp = root;
for(int i=0;i<n;i++)
{
cin>>rt>>a>>b>>c;
tmp = createTree(tmp,rt,a,b,c);
}
//pre_test(root);
int m;
cin>>m;
target t[m];
for(int i=0;i<m;i++)
{
cin>>t[i].target>>t[i].priority;
}
sort(t,t+m);
// for(int i=0;i<m;i++)
// {
// cout<<t[i].target<<" "<<t[i].priority<<endl;
// }
// triTree * node1 = search_node(root,15);
cout<<node->data<<" "<<node->parent->data<<endl;
// triTree *node2 = search_node(root,19);
// triTree *res = getNearestRoot(root,node1,node2);
// cout<<res->data<<endl;
// result.clear();
// preOrder(root,7);
// print();
triTree *tmp1 = root;
triTree *tmp2,*troot;
triTree *last = root;
for(int i=0;i<m;i++)
{
result.clear();
tmp2 = search_node(root,t[i].target);
troot = getNearestRoot(root,tmp1,tmp2);
while(last!=troot)
{
result.push_back(last->data);
last = last->parent;
}
preOrder(troot,t[i].target);
print();
cout<<tmp2->data<<" "<<endl;
tmp1 = tmp2;
last = search_node(root,result.back());
}
while(last!=NULL)
{
cout<<last->data<<" ";
last = last->parent;
}
cout<<endl;
}
点评:这个题按以上分析,十分复杂,考察的点非常多,要求关于树的常用算法非常熟悉才可以在最多一个半小时完成。这里说一说都用到哪些数据结构和算法:首先是三叉树的数据结构,(为了处理方便增加parent指针),树的建立过程(用队列),结构体排序(sort函数以及操作符重载),前序遍历求节点,后序遍历求两个节点的最近公共父节点,前序遍历求叶子节点的路径等,细节非常多。近两年北航机考最后一题都是关于树有关的,难度都不低,建议决定报考北航的考生注意这一部分程序设计的实战。
转载请注明出处