问题 A: 二叉树非递归前序遍历-附加代码模式
用二叉树的带虚结点表示的前序遍历序可以唯一的确定一棵二叉树,请用非递归算法实现二叉树的前序遍历。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
struct BiNode
{
string data;
BiNode *lchild, *rchild;
};
typedef BiNode *BiTree;
int InitBiTree(BiTree &T)
{
T = NULL;
return 0;
}
// 非递归前序遍历,返回遍历结果字符串
string PreTraverse_nonRec(BiTree T)
{
string result = "";
stack<BiTree>st;
if(T==NULL) return result;
st.push(T);
while(!st.empty()){
BiTree node=st.top();
st.pop();
result=result+node->data;
if(node->rchild) st.push(node->rchild);
if(node->lchild) st.push(node->lchild);
}
return result;
}
// 用带虚结点的前序遍历串str(每个字符对应一个结点)构造二叉树T,并返回剩余字符串
char *CreateBiTree(BiTree &T, char *str)
{
// 约定#表示空结点
if (*str == '#')
{
T = NULL;
return str + 1;
}
// 创建结点
T = new BiNode;
T->data = *str;
// 继续输入并构造左子树和右子树
char * strAfterLeft = CreateBiTree(T->lchild, str + 1);
char * strAfterRight = CreateBiTree(T->rchild, strAfterLeft);
// 返回剩余的字符串
return strAfterRight;
}
int PreTraverse(BiTree T){
if (T == NULL) return 0;
cout << T->data;
PreTraverse(T->lchild);
PreTraverse(T->rchild);
return 0;
}
int DestroyBiTree(BiTree &T){
if (T == NULL) return 0;
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
delete T;
T = NULL;
return 0;
}
// please comment the following code when you sumbit to OJ
/*int main(){
// char *str = "abd###ceg##h##f#i##";
char str[2000];
while(cin >> str)
{
BiTree tree;
InitBiTree(tree);
// 根据带空节点的前序遍历字符串构造二叉树
CreateBiTree(tree, str);
// 前序遍历递归算法
PreTraverse(tree);
cout << endl;
// 前序遍历非递归算法
string result = PreTraverse_nonRec(tree);
cout << result << endl;
DestroyBiTree(tree);
}
return 0;
}*/
问题 B: 二叉树非递归中序遍历-附加代码模式
用二叉树的带虚结点表示的前序遍历序可以唯一的确定一棵二叉树,请用非递归算法实现二叉树的中序遍历。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
struct BiNode
{
string data;
BiNode *lchild, *rchild;
};
typedef BiNode *BiTree;
int InitBiTree(BiTree &T)
{
T = NULL;
return 0;
}
// 非递归中序遍历,返回遍历结果字符串
string InTraverse_nonRec(BiTree T)
{
// please write your code here
string result = "";
if(T==NULL) return result;
stack<BiTree>st;
while(!st.empty()||T){
while(T){
st.push(T);
T=T->lchild;
}
T=st.top();
st.pop();
result=result+T->data;
T=T->rchild;
}
return result;
}
// 用带虚结点的前序遍历串str(每个字符对应一个结点)构造二叉树T,并返回剩余字符串
char *CreateBiTree(BiTree &T, char *str)
{
// 约定#表示空结点
if (*str == '#')
{
T = NULL;
return str + 1;
}
// 创建结点
T = new BiNode;
T->data = *str;
// 继续输入并构造左子树和右子树
char * strAfterLeft = CreateBiTree(T->lchild, str + 1);
char * strAfterRight = CreateBiTree(T->rchild, strAfterLeft);
// 返回剩余的字符串
return strAfterRight;
}
int InTraverse(BiTree T){
if (T == NULL) return 0;
InTraverse(T->lchild);
cout << T->data;
InTraverse(T->rchild);
return 0;
}
int DestroyBiTree(BiTree &T){
if (T == NULL) return 0;
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
delete T;
T = NULL;
return 0;
}
// please comment the following code when you sumbit to OJ
/*int main(){
// char *str = "abd###ceg##h##f#i##";
char str[2000];
while(cin >> str)
{
BiTree tree;
InitBiTree(tree);
// 根据带空节点的前序遍历字符串构造二叉树
CreateBiTree(tree, str);
// 中序遍历递归算法
InTraverse(tree);
cout << endl;
// 中序遍历非递归算法
string result = InTraverse_nonRec(tree);
cout << result << endl;
DestroyBiTree(tree);
}
return 0;
}*/
问题 C: 二叉树非递归后序遍历-附加代码模式
用二叉树的带虚结点表示的前序遍历序可以唯一的确定一棵二叉树,请用非递归算法实现二叉树的后序遍历。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include<algorithm>
using namespace std;
struct BiNode
{
string data;
BiNode *lchild, *rchild;
};
typedef BiNode *BiTree;
int InitBiTree(BiTree &T)
{
T = NULL;
return 0;
}
// 非递归中序遍历,返回遍历结果字符串
string SucTraverse_nonRec(BiTree T)
{
// please write your code here
string result = "";
if(T==NULL) return result;
stack<BiTree>st;
st.push(T);
while(!st.empty()){
BiTree node=st.top();
st.pop();
result=result+node->data;
if(node->lchild) st.push(node->lchild);
if(node->rchild) st.push(node->rchild);
}
reverse(result.begin(),result.end());
return result;
}
// 用带虚结点的前序遍历串str(每个字符对应一个结点)构造二叉树T,并返回剩余字符串
char *CreateBiTree(BiTree &T, char *str)
{
// 约定#表示空结点
if (*str == '#')
{
T = NULL;
return str + 1;
}
// 创建结点
T = new BiNode;
T->data = *str;
// 继续输入并构造左子树和右子树
char * strAfterLeft = CreateBiTree(T->lchild, str + 1);
char * strAfterRight = CreateBiTree(T->rchild, strAfterLeft);
// 返回剩余的字符串
return strAfterRight;
}
int SucTraverse(BiTree T){
if (T == NULL) return 0;
SucTraverse(T->lchild);
SucTraverse(T->rchild);
cout << T->data;
return 0;
}
int DestroyBiTree(BiTree &T){
if (T == NULL) return 0;
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
delete T;
T = NULL;
return 0;
}
// please comment the following code when you sumbit to OJ
/*int main(){
// char *str = "abd###ceg##h##f#i##";
char str[2000];
while(cin >> str)
{
BiTree tree;
InitBiTree(tree);
// 根据带空节点的前序遍历字符串构造二叉树
CreateBiTree(tree, str);
// 中序遍历递归算法
SucTraverse(tree);
cout << endl;
// 中序遍历非递归算法
string result = SucTraverse_nonRec(tree);
cout << result << endl;
DestroyBiTree(tree);
}
return 0;
}*/
问题 D: 求二叉树中序遍历序根节点的下标
题目描述
用一棵二叉树的前序遍历序和中序遍历序可以唯一确定一棵二叉树,这个算法的核心操作是根据前序遍历序,查找中序遍历序中根节点的位置,以确定左子树序列,根节点,和右子树序列。然后递归找到每个子树的根节点就可以完成二叉树的构造。
前序遍历第一个字母就是根节点。在第二个字符串里查找它的下标即可。
#include <iostream>
#include <bits/stdc++.h>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include<algorithm>
using namespace std;
int main()
{
string a,b;
while(cin>>a>>b){
char ch=a[0];
for(int i=0;i<b.length();i++){
if(b[i]==ch){
cout<<i<<endl;
break;
}
}
}
return 0;
}
问题 E: 根据前序+中序还原二叉树
用一棵二叉树的前序遍历序和中序遍历序可以唯一确定一棵二叉树。
对于前序遍历中的任意两个连续节点 u 和 v,根据前序遍历的流程,我们可以知道 u 和 v 只有两种可能的关系:
v 是 u 的左儿子。这是因为在遍历到 uu 之后,下一个遍历的节点就是 u 的左儿子,即 v;
u 没有左儿子,并且 v 是 u 的某个祖先节点(或者 u 本身)的右儿子。如果 uu 没有左儿子,那么下一个遍历的节点就是 uu 的右儿子。如果 uu 没有右儿子,我们就会向上回溯,直到遇到第一个有右儿子(且 u 不在它的右儿子的子树中)的节点 ua,那么 v 就是 ua 的右儿子。
#include <iostream>
#include <bits/stdc++.h>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include<algorithm>
using namespace std;
typedef struct node{
struct node *l;
struct node *r;
char val;
}node,*tnode;
tnode buildtree(string a,string b){
if(!a.length()) return NULL;
tnode root=new node;
root->val=a[0];
stack<tnode>st;
st.push(root);
int index=0;
for(int i=1;i<a.length();i++){
char ch=a[i];
tnode rost=st.top();
if(rost->val!=b[index]){
rost->l=new node;
rost->l->val=ch;
st.push(rost->l);
}
else{
while(!st.empty()&&st.top()->val==b[index]){
rost=st.top();
st.pop();
index++;
}
rost->r=new node();
rost->r->val=ch;
st.push(rost->r);
}
}
return root;
}
void endsolve(tnode root){
if(root==NULL) return;
endsolve(root->l);
endsolve(root->r);
cout<<root->val;
}
int main()
{
string a,b;
while(cin>>a>>b){
tnode T=buildtree(a,b);
endsolve(T);
cout<<endl;
}
return 0;
}
问题 F: 算法6-12:自底向上的赫夫曼编码
#include <bits/stdc++.h>
using namespace std;
typedef struct node{
int l,r,fat,val;
}hoff;
hoff t[1005];
int check(int n){
for(int i=n;i<2*n-1;i++) t[i].val=0;
for(int i=0;i<2*n-1;i++) t[i].fat=t[i].l=t[i].r=-1;
for(int i=n;i<n*2-1;i++){
int min1=INT_MAX,min2=INT_MAX;
int ind1,ind2;
for(int j=0;j<i;j++){
if(t[j].val<min1&&t[j].fat==-1){
min1=t[j].val;
ind1=j;
}
}
t[ind1].fat=i;
for(int j=0;j<i;j++){
if(t[j].val<min2&&t[j].fat==-1&&j!=ind1){
min2=t[j].val;
ind2=j;
}
}
t[ind2].fat=i;
if(ind1>ind2){
swap(ind1,ind2);
swap(min1,min2);
}
t[i].val=min1+min2;
t[i].l=ind1;
t[i].r=ind2;
}
return 0;
}
int created(int n){
int start=0;
char ch[105];
for(int i=0;i<n;i++){
for(int j=i,par=t[i].fat;par!=-1;j=par,par=t[par].fat){
if(t[par].l==j) ch[start]='0';
else ch[start]='1';
start++;
}
string str;
while(start){
start--;
str=str+ch[start];
}
cout<<str<<endl;
start=0;
}
return 0;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>t[i].val;
check(n);
created(n);
return 0;
}
问题 G: 视频合并问题
题目描述
有多个视频需要合并为一个视频,假设一次只能将两个视频进行合并,合并需要的时间为该两个视频的时间之和。请计算将多个视频合并为一个视频需要的最小时间为多少?
每次挑最小的两个合并,合并后塞回数组。可以考虑用 priority_queue。
#include <iostream>
#include <bits/stdc++.h>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include<algorithm>
using namespace std;
int a[10086];
bool cmp(int a,int b){
return a>b;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int sum=0;int t=0;
for(int i=n-1;i>0;i--){
sort(a,a+i+1,cmp);
t=a[i-1]+a[i];
sum+=t;
a[i-1]=t;
}
cout<<sum;
return 0;
}
问题 H: 二叉树实现的简单物种识别系统-附加代码模式
用二叉树可以实现一个简单的物种识别系统,举例如下:
请编写代码根据上面的系统完成物种识别过程。注意问题对应的左节点表示回答的是no,右节点表示回答的yes
太坑了,给的模板写好的地方不全是对的,还要再补上,不然会MLE。。。
函数头不是void 的,都把 return 补上。
#include <bits/stdc++.h>
using namespace std;
struct BiNode
{
string data;
BiNode *lchild, *rchild;
};
typedef BiNode *BiTree;
int InitBiTree(BiTree &T)
{
T = nullptr;
return 0;
}
BiTree getNode(string data){
BiTree node = new BiNode;
node->data = data;
node->lchild = nullptr;
node->rchild = nullptr;
return node;
}
BiNode *StartRecognize(BiTree T)
{
/*BiTree n3 = getNode("rabbit");
BiTree n4 = getNode("tiger");
BiTree n5 = getNode("swallow");
BiTree n6 = getNode("eagle");*/
BiTree p=T;
/*char a,b;
cin>>a>>b;
if((a=='y'||a=='Y')&&(b=='y'||b=='Y')) p=getNode("eagle");
if((a=='y'||a=='Y')&&(b=='n'||b=='N')) p=getNode("swallow");
if((a=='n'||a=='N')&&(b=='y'||b=='Y')) p=getNode("tiger");
if((a=='n'||a=='N')&&(b=='N'||b=='n')) p=getNode("rabbit");*/
char c;
for(int i=0;i<2;i++){
cin>>c;
if(c=='y'||c=='Y') p=p->rchild;
else p=p->lchild;
}
return p;
}
/*
// please comment the following code when you sumbit to OJ
// 构造一个三层的物种识别系统,第一层是一个问题,第二层是两个问题,第三层是四种动物
BiTree setRecognizeSystem(){
BiTree T = getNode("Can it fly?");
BiNode* n1 = getNode("Is it dangerous");
BiNode* n2 = getNode("Does it eat meat?");
BiNode* n3 = getNode("rabbit");
BiNode* n4 = getNode("tiger");
BiNode* n5 = getNode("swallow");
BiNode* n6 = getNode("eagle");
T->lchild = n1; T->rchild = n2;
n1->lchild = n3; n1->rchild = n4;
n2->lchild = n5; n2->rchild = n6;
return T;
}
int main(){
// freopen("/config/workspace/answer/BiTreeFiles/test.in","r",stdin);
BiTree T = setRecognizeSystem();
BiNode *p = StartRecognize(T);
if(p != nullptr) cout << "the answer is:" << p->data << endl;
return 0;
}
*/
问题 I: 静态链表存储的二叉树查找根节点
题目描述
用数组模拟实现链表的功能,即静态链表,也可以用来存储二叉树。
请编写程序,输出静态链表存储的二叉树的根节点
记录下哪个数字没出现过就行了。
#include <iostream>
#include <bits/stdc++.h>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include<algorithm>
using namespace std;
int main()
{
int n;
while(cin>>n){
if(n==0){
int x;
cin>>x;
cout<<endl;
}
else{
char a[555];
int num[105]={0};
for(int i=0;i<n;i++){
cin>>a[i];
char x,y;
cin>>x>>y;
if(x<='9'&&x>='0') num[x-'0']=1;
if(y<='9'&&y>='0') num[y-'0']=1;
}
for(int i=0;i<10;i++) if(!num[i]){
cout<<a[i]<<endl;
break;
}
}
}
return 0;
}
问题 J: 基础实验4-2.1:树的同构
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。现给定两棵树,请你判断它们是否是同构的。
dalao的思路。遍历每一个根节点和他的子树,如果不对称就No
#include <bits/stdc++.h>
using namespace std;
struct node{
int l,r;
char val;
}a[66],b[66];
map<char,int>mp;
char s1,s2,s3;
bool check(int x,int y){
if(a[x].val!=b[y].val) return 0;
if(a[a[x].l].val==b[b[y].l].val&&a[a[x].r].val==b[b[y].r].val) return 1;
if(a[a[x].l].val==b[b[y].r].val&&a[a[x].r].val==b[b[y].l].val) return 1;
return 0;
}
int main()
{
int n,m;
cin>>n;
for(int i=0;i<n;i++){
cin>>s1>>s2>>s3;
//mp[s1]=i;
a[i].val=s1;
a[i].l=(s2=='-'?11:s2-'0');
a[i].r=(s3=='-'?11:s3-'0');
}
cin>>m;
if(m!=n){
cout<<"No";
//cout<<65;
return 0;
}
for(int i=0;i<m;i++){
cin>>s1>>s2>>s3;
b[i].val=s1;
mp[b[i].val]=i;
b[i].l=(s2=='-'?11:s2-'0');
b[i].r=(s3=='-'?11:s3-'0');
}
bool fl=1;
for(int i=0;i<n;i++){
if(!check(i,mp[a[i].val])){
cout<<"No";
return 0;
fl=0;
}
}
cout<<"Yes";
return 0;
}
问题 K: 哈夫曼树--查找值最小的两个叶节点
题目描述
哈夫曼树的构造过程,最重要的是找到值最小的两个叶节点。
#include <bits/stdc++.h>
using namespace std;
int main()
{
pair<int,int> a[10086];
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i].first;
a[i].second=i;
}
sort(a,a+n);
cout<<a[0].second<<" "<<a[1].second;
return 0;
}
问题 L: 静态链表存储的二叉树的非递归遍历算法-附加代码模式
用数组模拟实现链表的功能,即静态链表,也可以用来存储二叉树。
请编写程序,用非递归遍历算法输出静态链表存储前中后三种遍历结果。
本题为附加代码模式,以下代码为自动附加在同学们提交的代码后面。在本题的提示中有代码框架
不会了,copy大佬的。
#include <bits/stdc++.h>
using namespace std;
struct BiNode{
char data;
char lchild;
char rchild;
int flag = 0;
};
struct BiTree{
int nodeNumber;
BiNode data[10];
int rootIndex;
};
void FindRootIndex(BiTree &T){
vector<char> v;
for (int i = 0; i < T.nodeNumber; ++i) {
if (T.data[i].lchild != '-') v.push_back(T.data[i].lchild-'0');
if (T.data[i].rchild != '-') v.push_back(T.data[i].rchild-'0');
}
for (int i = 0; i < T.nodeNumber; ++i) {
if (find(v.begin(), v.end(), i) == v.end()){
T.rootIndex = i;
return;
}
}
}
string getPreTraverseStr(const BiTree &T){
if (T.nodeNumber <= 0) return "";
string s;
stack<BiNode> sta;
sta.push(T.data[T.rootIndex]);
while (!sta.empty()){
BiNode t;
t = sta.top();
sta.pop();
s += t.data;
if (t.rchild != '-') sta.push(T.data[t.rchild-'0']);
if (t.lchild != '-') sta.push(T.data[t.lchild-'0']);
}
return s;
}
string getInTraverseStr(const BiTree &T){
if (T.nodeNumber <= 0) return "";
string s;
stack<BiNode> sta;
sta.push(T.data[T.rootIndex]);
while(!sta.empty()){
if (sta.top().flag == 0){
sta.top().flag++;
if (sta.top().lchild != '-') {
sta.push(T.data[sta.top().lchild - '0']);
}
}
else{
BiNode t;
t = sta.top();
sta.pop();
s += t.data;
if (t.rchild != '-')
sta.push(T.data[t.rchild-'0']);
}
}
return s;
}
string getSucTraverseStr(const BiTree &T){
if (T.nodeNumber<=0) return "";
string s;
stack<BiNode> sta;
sta.push(T.data[T.rootIndex]);
while (!sta.empty()){
if (sta.top().flag == 0){
sta.top().flag++;
if (sta.top().lchild != '-')
sta.push(T.data[sta.top().lchild-'0']);
}
else if (sta.top().flag == 1){
sta.top().flag++;
if (sta.top().rchild != '-')
sta.push(T.data[sta.top().rchild-'0']);
}
else{
s += sta.top().data;
sta.pop();
}
}
return s;
}
/*
// please comment the following code when you sumbit to OJ
void InputBiTree(BiTree & T){
cin >> T.nodeNumber;
for(int i=0;i<T.nodeNumber;i++){
cin >> T.data[i].data >> T.data[i].lchild >> T.data[i].rchild;
}
}
int main(){
//freopen("/config/workspace/answer/test.in","r",stdin);
BiTree T;
InputBiTree(T);
FindRootIndex(T);
string str = getPreTraverseStr(T);
cout << str << endl;
str = getInTraverseStr(T);
cout << str << endl;
str = getSucTraverseStr(T);
cout << str << endl;
InputBiTree(T);
FindRootIndex(T);
str = getPreTraverseStr(T);
cout << str << endl;
str = getInTraverseStr(T);
cout << str << endl;
str = getSucTraverseStr(T);
cout << str << endl;
return 0;
}*/