基础练习之二叉树

二叉树的构建与遍历

利用几个题目来回顾下如何根据二叉树的不同遍历次序构建一棵树,之后再对这棵树进行相应的操作。

1.sdut problem 1489 - 求二叉树的先序遍历

题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1489

题目大意

根据二叉树的后序遍历与中序遍历,求先序遍历。

题解

根据两个顺序,可以递归的将一棵树建立,之后递归输出数的先序遍历。

代码如下:

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn = 100;
int t;
char s1[maxn], s2[maxn];
struct node {
    char key;
    node *lson, *rson;
    node():lson(NULL),rson(NULL){}
};
node* _build(node* p, int l, int r, int pos) {
    int i;
    bool flag = false;
    for(i = l; i <= r; i++) {
        if(s1[i] == s2[pos]) {
            flag = true;
            break;
        }
    }
    if(!flag)return NULL;
    p = new node();
    p->key = s1[i];
    p->lson = _build(p->lson, l, i-1, pos-1-(r-i));
    p->rson = _build(p->rson, i+1, r, pos-1);
    return p;
}
void _pre(node* p) {
    if(p != NULL) {
        printf("%c", p->key);
        _pre(p->lson);
        _pre(p->rson);
    }
}
int main() {
    while(~scanf("%d", &t)) {
        while(t--) {
            scanf("%s%s", s1, s2);
            int len = strlen(s1);
            node *root;
            root = _build(root, 0, len-1, len-1);
            _pre(root);
            printf("\n");
        }
    }
    return 0;
}

2.PAT 天梯赛 L2-006 树的遍历

题目链接:https://www.patest.cn/contests/gplt/L2-006

题目大意

根据二叉树的中序遍历与后序遍历,输出层次遍历序列。

题解

同样构建一棵树,利用BFS得到层次遍历。

代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 35;
int n;
int s1[maxn],s2[maxn];
struct node {
    int key;
    node *lson, *rson;
    node():lson(NULL),rson(NULL){}
}*root;

node* _build(node* p, int l, int r, int pos) {
    int i;
    bool flag = false;
    for(i = l; i <= r; i++) {
        if(s1[pos] == s2[i]) {
            flag = true;
            break;
        }
    }
    if(!flag) return NULL;
    p = new node();
    p->key = s1[pos];
    p->lson = _build(p->lson, l, i-1, pos-1-(r-i));
    p->rson = _build(p->rson, i+1, r, pos-1);
    return p;
}
void bfs() {
    queue<node*> q;
    q.push(root);
    int cnt = 0;
    while(!q.empty()) {
        node *p = q.front(); q.pop();
        if(cnt) printf(" ");
        cnt = 1;
        printf("%d", p->key);
        if(NULL != p->lson) {
            q.push(p->lson);
        }
        if(NULL != p->rson) {
            q.push(p->rson);
        }
    }
    printf("\n");
}
int main() {
    while(~scanf("%d", &n)) {
        for(int i = 0; i < n; i++) {
            scanf("%d", &s1[i]);
        }
        for(int i = 0; i < n; i++) {
            scanf("%d", &s2[i]);
        }
        root = _build(root, 0, n-1, n-1);
        bfs();
    }
    return 0;
}

3.UVa problem 122 - Trees on the level

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=838&page=show_problem&problem=58

题目大意

输入一棵二叉树,每个节点都是按照从根节点到它的移动序列给出(数字表示节点的编号,L表示左,R表示右边)。现在根据给出的信息输出这棵树的层次遍历序列。

题解

按照给的节点,模拟建立一棵树。之后用一次BFS得到树的层次遍历。

代码如下:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 300;
char s[maxn];
bool failed;
vector<int> ans;
struct Node {
    bool have_value;
    int v;
    Node *left, *right;
    Node():have_value(false),left(NULL),right(NULL){}
}*root;

void _build(int v, char *s) {
    Node *u = root;
    int len = strlen(s);
    for(int i = 0; i < len; i++) {
        if('L' == s[i]) {
            if(NULL == u->left) u->left = new Node();
            u = u->left;
        }else if('R' == s[i]) {
            if(NULL == u->right) u->right = new Node();
            u = u->right;
        }
    }
    if(u->have_value){
        failed = true;
        return ;
    }
    u->have_value = true;
    u->v = v;
}

bool read_input() {
    failed = false;
    root = new Node();
    while(true) {
        if(scanf("%s", s) != 1) return false;
        if(!strcmp(s, "()")) break;
        int v;
        sscanf(&s[1], "%d", &v);
        _build(v, s);
    }
    return true;
}

bool bfs() {
    ans.clear();
    queue<Node*> q;
    q.push(root);
    while(!q.empty()) {
        Node *u = q.front(); q.pop();
        if(!u->have_value) return false;
        ans.push_back(u->v);
        if(u->left != NULL) {
            q.push(u->left);
        }
        if(u->right != NULL) {
            q.push(u->right);
        }
    }
    return true;
}
int main() {
    while(read_input()) {
        if(!bfs()) failed = true;
        if(failed) {
            printf("not complete\n");
        }else {
            for(int i = 0; i < ans.size(); i++) {
                if(i) printf(" ");
                printf("%d", ans[i]);
            }
            printf("\n");
        }
    }
    return 0;
}

4.UVa problem 548 - Tree

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=838&page=show_problem&problem=489

题目大意

给一棵点带权的二叉树的后序遍历与中序遍历,找到一个叶子使得它到跟的路径上的权和最小,如果有多解,输出叶子权值最小的那个。

题解

构建二叉树,DFS递归的遍历这棵树,得到解。

代码如下:

#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxn = 10000+10;
const int inf = 0x3f3f3f3f;
int inorder[maxn],postorder[maxn];
int n, _min, ans;
struct Node {
    int value;
    Node *lson, *rson;
    Node():lson(NULL),rson(NULL){}
}*root;

Node* _build(Node* p, int l, int r, int pos) {
    int i;
    bool flag = false;
    for(i = l; i <= r; i++) {
        if(postorder[pos] == inorder[i]) {
            flag = true;
            break;
        }
    }
    if(!flag) return NULL;
    p = new Node();
    p->value = postorder[pos];
    p->lson = _build(p->lson, l, i-1, pos-1-(r-i));
    p->rson = _build(p->rson, i+1, r, pos-1);
    return p;
}

void _find(Node *p, int sum) {
    if(NULL == p)return ;
    sum += p->value;
    if(NULL == p->lson && NULL == p->rson) {
        if(_min > sum) {
            _min = sum;
            ans = p->value;
        }else if(_min == sum) {
            ans = (ans > p->value ? p->value: ans);
        }
        return ;
    }
    _find(p->lson, sum);
    _find(p->rson, sum);
    return ;
}

bool read_input(int *a) {
    string line;
    if(!getline(cin, line)) return false;
    int x;
    n = 0;
    stringstream ss(line);
    while(ss >> x)a[n++] = x;
    return n>0;
}

int main() {
    while(read_input(inorder)) {
        read_input(postorder);
        root = _build(root, 0, n-1, n-1);
        _min = inf;
        ans = inf;
        _find(root, 0);
        printf("%d\n", ans);
    }
    return 0;
}

参考资料

posted @ 2016-05-22 20:26  yinzm  阅读(456)  评论(0编辑  收藏  举报