ACM新手DAY 9 二叉树+哈弗曼树+字典树

题解

A - 后序遍历

题目:给一个二叉树的前序遍历和中序遍历,求出它的后序遍历。

  • 二叉树
  • 三种遍历的关系
  • 具体方法题目已经给的很详细了,这里直接在代码里标出
#include <iostream>
#include <string>
using namespace std;
string str1, str2;
string find(int begin1, int begin2, int len)
{
    int i;
    if(len == 0)
        return ""; //递归终止了
    for(i = begin2; i < begin2+len; i++)//从中序遍历中找到根节点并记录
    {
        if(str2[i] == str1[begin1])//str1[begin1]对应的就是root
            break;
    }
    //子树的前序遍历和中序遍历的长度一样,所以左子树的长度就是i-begin2
    string str1L = find(begin1+1, begin2, i - begin2);
    string str1R = find(begin1+1+(i - begin2), i+1, len-(i - begin2)-1);
    return str1L + str1R + str1[begin1];//这个东西就是post_order(str1, str2)=post_order(str1l, str2l)+post_order(str1r, str2r)+root
}
int main()
{
    cin >> str1 >> str2;
    cout << find(0, 0, str1.length()) << endl;
    return 0;
}

B - Dropping Balls (补题)

题目:一颗二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为 1 , 2 2 D 1 1,2,···2^D-1 。在结点1放一个小球,它会下落。每个内结点上有一个开关,每当有小球落上去,开关状态都会改变。当小球到达一个结点时,若这个结点的开关关闭,则往左走,否则往右走,直到走到叶子结点。一些小球从结点1依次开始下落,最后一个小球将会落到哪里?

  • 完全二叉树+模拟
#include<cstdio>
#include<iostream>
using namespace std;

int main()
{
    int n;
    while(scanf("%d",&n)&& n!=-1)
    {
        for(int i=0; i<n; i++)
        {
            int D,I;
            scanf("%d%d",&D,&I);
            int ans=1;//左边就是2倍,右边就是2倍加1
            for(int j=1; j<D; j++)
            {
                if(I%2)
                {
                    ans=ans*2;
                    I=I/2+1;
                }
                else
                {
                    ans=ans*2+1;
                    I=I/2;
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

H - Trie树 (样题)

  • 字典树
  • 学长的模板,用了很多指针的东西,放下代码留着看
#include <bits/stdc++.h>

typedef long long ll;
const int INF = 1 << 30;
const int maxn = 2*1e5+10;
using namespace std;

struct trie_node
{
    int cnt;            ///以该串为前缀串的字符串个数
    bool flag;          ///判断从根结点到该结点的单词是否存在字典中
    trie_node *child[30];///指向他的孩子结点
};

trie_node* creat_node() ///创建一个新结点并初始化
{
    trie_node *node = new trie_node();
    node->cnt = 0;
    node->flag = false;
    for(int i=0; i<30; i++)
        node->child[i] = NULL;

    return node;
}

void insert_node(trie_node *root, string key)
{
    int i=0;
    trie_node *node = root;

    while(i<key.size())
    {
        if(node->child[key[i]-'a'] == NULL)         ///key[i]-'a'是ascii码,判断他是第几个字母,如果node->child[0]存在
            node->child[key[i]-'a'] = creat_node(); ///则说明该结点有存a的子结点

        node = node->child[key[i]-'a'];             ///修改指针,使它指向它的子结点,
        node->cnt++;                                ///计数位加1
        i++;                                        ///这里用for实现更简洁一点
    }
}

int search_trie(trie_node *root, string key)
{
    int i=0;
    trie_node *node = root;

    while(i<key.size())
    {
        if(node->child[key[i]-'a'] == NULL)         ///如果为空则这个字符不存在字典树中
            return 0;

        node = node->child[key[i]-'a'];
        i++;
    }

    return node->cnt;                               ///返回计数位
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int n, m;
    string s1, s2;
    cin >>n;
    trie_node *root = new trie_node();
    for(int i=0; i<n; i++)
    {
        cin >>s1;
        insert_node(root, s1);
    }
    cin >>m;
    for(int i=0; i<m; i++)
    {
        cin >>s2;
        cout <<search_trie(root, s2) <<endl;
    }

    return 0;
}

发布了47 篇原创文章 · 获赞 4 · 访问量 1313

猜你喜欢

转载自blog.csdn.net/listenhhh/article/details/97025932