PAT1064 Complete Binary Search Tree

1. 养成在三元运算符?:两边加括号的习惯。复杂算术表达式最好加括号。

2.报错Thread 1: EXC_BAD_ACCESS则重点检查指针或数组下标。如果用了递归,则首先检查递归出口,极有可能是过晚退出递归造成的越界访问。比如退出递归的条件中左右坐标的关系带不带等号,有时是相等一种退出、小于另一种退出。

3.把中间结果打印出来有助于定位错误。

4.preSequence函数通过计算左子树结点个数来递归确定根结点的值,依次存起来得到的就是先序遍历序列。结合从小到大的中序遍历序列就可唯一确定一棵树,进而对其层次遍历。

5.只看题目不知道怎么解时,可以从样例输出入手,倒推求解过程。

6.写的时候注意细节要比后面代码跑不了debug找错误高效得多。

7.书上的方法和代码很简洁,但没太懂,回头有机会再看。

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define MAXN 1005
using namespace std;

int N, a[MAXN];
struct node{
    int data;
    node *lchild;
    node *rchild;
};

int preCount = 0;
int preOrder[MAXN];
void preSequence(int l, int r){
    if (l == r) {//
        preOrder[preCount++] = a[l];
        return;
    }
    if (l > r) {//
        return;
    }
    
    int n = r - l + 1;//一开始写成l - r + 1了,导致32行Thread 1: EXC_BAD_ACCESS
    int h = 1;
    while (true) {
        if (pow(2, h) - 1 >= n) {
            break;
        }
        h++;
    }
    int lastLayerCount = n - (pow(2, h-1) - 1);
    int Lcount = (int)pow(2, h-2) - 1 + (lastLayerCount<(int)pow(2, h-2)?lastLayerCount:(int)pow(2, h-2));//后半部分加个括号才对
//    printf("Lcount  = %d\n", Lcount);
//    printf("l + Lcount  = %d\n", l+Lcount);
    preOrder[preCount++] = a[l + Lcount];//Thread 1: EXC_BAD_ACCESS
    
    preSequence(l, l + Lcount - 1);
    preSequence(l + Lcount + 1, r);
}

node* create(int preL, int preR, int inL, int inR){//root要加&
    if (preL > preR) {
        return NULL;
    }
    
    int i;
    for (i=inL; i<=inR; i++) {
        if (a[i] == preOrder[preL]) {
            break;
        }
    }
    int Lcount = i - inL;
    
    node *root = new node;
    root->data = a[i];//Thread 1: EXC_BAD_ACCESS
    root->lchild = create(preL+1, preL+Lcount, inL, i-1);
    root->rchild = create(preL+Lcount+1, preR, i+1, inR);
    return root;
}

int layerCount = 0;
int layerResult[MAXN];
void layerOrder(node *root){
    if (root == NULL) {
        return;
    }
    
    queue<node*> q;
    while (!q.empty()) {
        q.pop();
    }
    
    q.push(root);
    while (!q.empty()) {
        node *temp;
        temp = q.front();
        layerResult[layerCount++] = temp->data;
        q.pop();
        
        if (temp->lchild!=NULL) {
            q.push(temp->lchild);
        }
        if (temp->rchild!=NULL) {
            q.push(temp->rchild);
        }
    }
}

int main(int argc, const char * argv[]) {
    scanf("%d", &N);
    for (int i=0; i<N; i++) {
        scanf("%d", &a[i]);
    }
    
    //确定先序遍历序列
    sort(a, a+N);
    preSequence(0, N-1);
//    for (int i=0; i<N; i++) {//test
//        printf("%d ", preOrder[i]);
//    }
//    printf("\n");
    
    //由先序遍历序列和中序遍历序列建树
    node* root = new node;
    root = create(0, N-1, 0, N-1);
    
    //层次遍历
    layerOrder(root);
    for (int i=0; i<N; i++) {
        printf("%d", layerResult[i]);
        if (i < N - 1) {
            printf(" ");
        }
    }
    return 0;
}



//Sample Input:
//10
//1 2 3 4 5 6 7 8 9 0
//Sample Output:
//6 3 8 1 5 7 9 0 2 4


//1.75小时,傍晚0.5小时debug,提交倒是一遍过了,但debug耗时过长。合计约2小时15分钟。太慢。多写多学。
//BST相关的题目似乎边界测试不多,基本上样例过了就能AC
//主要就是写的时候犯下的一些细节错误不好找,导致debug较长时间。最好写的时候就细心,争取写好之后一遍就能运行。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值