销魂结构作业8

问题 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;
}*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值