PAT A1064 Complete Binary Search Tree 03-树3 Tree Traversals Again(一棵树建立为完全二叉搜索树)

该博客介绍了如何使用栈非递归地实现二叉树的中序遍历,并通过给定的中序遍历序列构建特定的二叉树。接着,给出了两种不同的实现方式,一种是使用指针实现,另一种是使用数组实现。最后,提供了相应的代码示例,展示如何进行后序遍历。
摘要由CSDN通过智能技术生成

03-树3 Tree Traversals Again

分数 25

作者 陈越

单位 浙江大学

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.


Figure 1

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: "Push X" where X is the index of the node being pushed onto the stack; or "Pop" meaning to pop one node from the stack.

Output Specification:

For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

建立一棵完全二叉搜索树,用指针实现:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef struct TNode* Bin;
struct TNode
{
    int v;
    Bin l, r;
};

const int N = 1010;
int a[N];
int flag = 1;

Bin NewNode(int v)
{
    Bin t = new TNode;
    t->v = v;
    t->l = t->r = NULL;
    return t;
}

Bin insert(int num, int l, int r)
{
    //h是num个结点能构成完全二叉树的层数先下取整,sum是构成满二叉树的节点数
    int h = 1, sum = 0;
    while(sum+h <= num)
    {
        sum += h;
        h += h;
    }
    
    //rest为最后一层不是满二叉树的节点数量
    int rest = num - sum;
    //左子树的节点数量
    int lnum = min(rest, h/2) + sum/2;
    //右子树的节点数量
    int rnum = max(0, rest - h/2) + sum/2;
    Bin t = NULL;
    t = NewNode(a[l + lnum]);
    if(lnum >= 1) //如果左子树有节点
        t->l = insert(lnum, l, l+lnum-1);
    if(rnum >= 1) //如果右子树有节点
        t->r = insert(rnum, l+lnum+1, r);
    return t;
}

void lay_traver(Bin root)
{
    queue<Bin> q;
    q.push(root);
    
    while(q.size())
    {
        Bin u = q.front();
        q.pop();
        if(flag)
            flag = 0;
        else
            cout << ' ';
        cout << u->v;
        if(u->l)
            q.push(u->l);
        if(u->r)
            q.push(u->r);
    }
}

int main()
{
    int n;
    cin >> n;
    for(int i=0; i<n; ++i)
        cin >> a[i];
      
    sort(a, a+n);
    
    Bin root = NULL;
    root = insert(n, 0, n-1);
    
    lay_traver(root);
    
    return 0;
}

一棵树建立为完全二叉搜索树,数组实现,浙大数据结构代码:


#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

const int maxn=2010;
int a[maxn],lev[maxn];

void solve(int index,int l,int r); //将原数组合适的位置的值填到 lev[index] 数组里

int main()
{
    int n;
    cin >> n;
    for(int i=1;i<=n;++i)
        cin >> a[i];
    sort(a+1,a+n+1); //将原数组排好序
    solve(1,1,n);
    for(int i=1;i<=n;++i)
    {
        if(i!=1)
            cout << ' ';
        cout << lev[i];
    }
    return 0;
}

void solve(int index,int l,int r) //将原数组合适的位置的值填到 lev[index] 数组里
{
    if(l>r)  //如果区间内没有元素就返回
        return ;
    if(l==r) //如果区间内只有一个元素
    {
        lev[index]=a[l];
        return;
    }

    int sum=r-l+1;
    int H=log(sum+1) / log(2); // H=floor( log2(sum+1))
    int numL;
    int rest=sum-(int)pow(2,H)+1;  //计算最后一排的节点数
    if(rest <= (int)pow(2,H-1) )  //如果最后一排的节点数完全在左子树上
        numL=(int)pow(2,H-1) - 1 + rest;  //那么就可以把rest的结点数加到numL上
    else
        numL=(int)pow(2,H-1) - 1 +(int)pow(2,H-1); //否则只能加pow(2,H-1);
    lev[index]=a[l+numL];
    solve(2*index,l,l+numL-1); //递归左子树
    solve(2*index+1,l+numL+1,r);  //递归右子树
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值