美文网首页
二叉树求第三种遍历序列 Trie

二叉树求第三种遍历序列 Trie

作者: 无令便逐风 | 来源:发表于2018-04-10 00:09 被阅读0次

二叉搜索树

二叉搜索树(Binary Search Tree)它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉搜索树。
二叉搜索树能高效进行如下操作

  • 插入一个数值
  • 查询是否包含某个数值
  • 删除某个数值
比较繁琐的地方是删除结点时, 对于 "需要删除的结点" 而言分3种情况
(所谓提上去是指提到现在需要删除的结点的位置)
1. 没有左儿子,那么就把右儿子提上去
2. 左儿子没有右儿子,把左儿子提上去
3. 以上2种情况都不满足,把左儿子的子孙中最大的结点提上去
struct nd {
    int val;
    nd *lch, *rch;
};

// 插入数值x
nd *insert(nd *p, int x) {
    if (p == NULL) {
        nd *q = new nd;
        q->val = x;
        q->lch = q->rch = NULL;
        return q;
    } else {
        if (x < p->val)
            p->lch = insert(p->lch, x);
        else
            p->rch = insert(p->rch, x);
        return p;
    }
}

// 是否存在数值x
bool find(nd *p, int x) {
    if (p == NULL) return 0;
    else if (x == p->val) return 1;
    else if (x < p->val) return find(p->lch, x);
    else return find(p->rch, x);
}

// 删除数值x, 返回删后链表的头指针
nd *remove(nd *p, int x) {
    if (p == NULL) return NULL;
    else if (x < p->val) p->lch = remove(p->lch, x);
    else if (x > p->val) p->rch = remove(p->rch, x);
    else if (p->lch == NULL){
        nd *q = p->rch;
        delete p;
        return q;
    }
    else if (p->lch->rch == NULL) {
        nd *q = p->lch;
        q->rch = p->rch;
        delete p;
        return q;
    } else {
        nd *q;
        for (q = p->lch; q->rch->rch != NULL; q = q->rch);
        nd *r = q->rch;
        q->rch = r->lch;
        r->lch = p->lch;
        r->rch = p->rch;
        delete p;
        return r;
    }
    return p;
}

Trie树,原理十分简单,看这道题就完事儿了。
这里权当备份个模板:

#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define maxN 1000005
char a[maxN];

struct Trie {
  int nxt[26], cnt;
  void init() {
    cnt = 0, memset(nxt, -1, sizeof nxt);
  }
} T[maxN];
int L;

void insert(string s) {
  int p = 0;
  FOR(i, 0, (int)s.size() - 1) {
    int r = s[i] - 'a';
    if (T[p].nxt[r] == -1) {
      T[L].init();
      T[p].nxt[r] = L++;
    }
    p = T[p].nxt[r];
    T[p].cnt++;
  }
}

void query(string s) {
  int p = 0;
  FOR(i, 0, (int)s.size() - 1) {
    int r = s[i] - 'a';
    if (T[p].nxt[r] == -1) {
      cout << 0 << endl;
      return;
    }
    p = T[p].nxt[r];
  }
  cout << T[p].cnt << endl;
}

int main () {
  // freopen("data.in", "r", stdin);
  int n, m;
  cin >> n;
  T[0].init();
  L = 1;
  string s;
  FOR(i, 0, n - 1) cin >> s, insert(s);
  cin >> m;
  while (m--) {
    cin >> s;
    query(s);
  }
  return 0;
}
样例树
        4
     /     \
    1       6
     \     /   \
      3   5     7
     /
   2
前中求后序
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

#define mst(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(a);i<(b);++i)

const int maxN = 35;
int N, M;
struct node { int v; node *lc, *rc; };
int mid[maxN], pre[maxN];

node* build(int *p, int *m, int len) {
    if (len == 0)
        return nullptr;
    node* prt = new node();
    prt->v = p[0];
    int idx;
    for (idx = 0; idx < len; ++idx)
        if (m[idx] == p[0])
            break;
    int lsz = idx, rsz = len - idx - 1;
    prt->lc = build(p + 1, m, lsz);
    prt->rc = build(p + 1 + lsz, m + idx + 1, rsz);
    return prt;
}
void print_path(node *prt) {
    if (prt == nullptr)
        return;
    print_path(prt->lc);
    print_path(prt->rc);
    printf("%d ", prt->v);
}

int main() {
    freopen("data.in", "r", stdin);
    scanf("%d", &N);
    rep(i, 0, N) scanf("%d", &mid[i]);
    rep(i, 0, N) scanf("%d", &pre[i]);

    node *prt = build(pre, mid, N);
    print_path(prt);
    return 0;
}

输入样例 节点个数+中序+前序:

7
1 2 3 4 5 6 7
4 1 3 2 6 5 7

输出样例:
2 3 1 5 7 6 4

后中求前序
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

#define mst(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(a);i<(b);++i)
const int maxN = 35;
int N, M;

struct node { node *lch, *rch; int v; };

node* build(int *mid, int *post, int len) {
    if (len == 0)
        return 0;
    int rt_idx;
    for (rt_idx = 0; rt_idx < len; ++rt_idx)
        if (mid[rt_idx] == *(post + len - 1))
            break;

    node *rt = new node;
    rt->v = mid[rt_idx];

    rt->lch = build(mid, post, rt_idx);
    rt->rch = build(mid + rt_idx + 1, post + rt_idx, len - (rt_idx + 1));
    return rt;
}

void print_tree(node *rt) {
    if (rt == nullptr)
        return;
    printf("%d ", rt->v);
    print_tree(rt->lch);
    print_tree(rt->rch);
}

int main() {
    // freopen("data.in", "r", stdin);

    int post[maxN], mid[maxN];
    scanf("%d", &N);
    rep(i, 0, N) scanf("%d", &mid[i]);
    rep(i, 0, N) scanf("%d", &post[i]);

    node* rt = build(mid, post, N);
    print_tree(rt);
    return 0;
}

输入样例 节点个数+中序+后序:

7
1 2 3 4 5 6 7
2 3 1 5 7 6 4

输出样例:
4 1 3 2 6 5 7

还遇到一道题:

知道一颗树的bfs遍历和dfs遍历序列.其中遍历过程选择孩子的时候,总是选序号小的
比如一棵树如图,其bfs序列为 4 3 5 1 2 8 7 6,dfs序列为4 3 1 7 2 6 5 8

       4
     /    \
    3       5
   /  \      \
  2    1      8
  |    | 
  6    7

目的是求树重建后,所有节点的子节点列表.注意,如果树不唯一,随意输出一棵
题目戳这里
方法是:把bfs理解成每个节点离root的距离.
把root入栈, 遍历dfs的每个点:

  • 若是当前点的距离 > 比栈顶元素距离+1, 意味着当前点是栈顶元素的孩子,图里做记录
  • 否则,要么应该是到了某个祖先节点的兄弟了,当前子树已经搜索完毕,不断出栈
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define pb push_back
const int maxN = 1e3 + 5;
int N, dis[maxN];
vector<int> G[maxN];


int main() {
    // freopen("data.in", "r", stdin);
    while (~scanf("%d", &N)) {
        int e;
        rep(i, 1, N + 1) {
            scanf("%d", &e);
            G[i].clear();
            dis[e] = i;
        }

        int rt;
        stack<int> st;
        scanf("%d", &rt);
        st.push(rt);

        rep(i, 1, N) {
            scanf("%d", &e);
            while (1) {
                int u = st.top();
                if (u == rt || dis[e] > dis[u] + 1) {
                    G[u].pb(e);
                    st.push(e);
                    break;
                } else {
                    st.pop();
                }
            }
        }

        rep(i, 1, N + 1) {
            printf("%lld:", i);
            rep(j, 0, G[i].size())
                printf(" %d", G[i][j]);
            puts("");
        }
    }
    return 0;
}

相关文章

网友评论

      本文标题:二叉树求第三种遍历序列 Trie

      本文链接:https://www.haomeiwen.com/subject/jdowhftx.html