題意:前序中序求後序
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1050;
int a[maxn],b[maxn];
int n;
struct node
{
int v,l,r;
}tr[maxn << 2];
int num = 0;
int build(int prel,int prer,int inl,int inr)
{
if(prer - prel < 0) return -1;
int id = num++;
tr[id].v = a[prel];
int mid= -1;
for(int i = inl; i <= inr; i++)
if(b[i] == a[prel]){mid = i;break;}
int lnum = mid - inl, rnum = inr-mid;
if(lnum >= 1)tr[id].l = build(prel+1,prel+lnum,inl,mid-1);
if(rnum >= 1)tr[id].r = build(prel+1+lnum,prer,mid+1,inr);
return id;
}
int flag = 0;
void order(int i)
{
if(tr[i].l != -1)order(tr[i].l);
if(tr[i].r != -1)order(tr[i].r);
if(flag == 0)
{
printf("%d",tr[i].v);
flag = 1;
}
else printf(" %d",tr[i].v);
}
int main()
{
while(~scanf("%d",&n))
{
num = 0; flag = 0;
for(int i = 0; i < n; i++) tr[i].l = tr[i].r = -1;
for(int i = 1; i <= n ; i++) scanf("%d",&a[i]);
for(int j = 1; j <= n ; j++) scanf("%d",&b[j]);
build(1,n,1,n);
order(0);
printf("\n");
}
return 0;
}
題意:輸入噁心,然後層次輸出二叉樹
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include <queue>
using namespace std;
const int maxn = 1024;
const int maxm = 1e4;
struct node
{
int v,l,r;
}tr[maxn];
char s[maxm];
int out[maxn];
void print(int mark)
{
if(mark == 1) {printf("not complete\n"); return;}
queue<node> Q;
Q.push(tr[1]);
int thnum = 0;
while(!Q.empty())
{
node temp = Q.front(); Q.pop();
int v = temp.v;
out[thnum++] = v;
if(temp.l) Q.push(tr[temp.l]);
if(temp.r) Q.push(tr[temp.r]);
}
for(int i = 0; i < thnum; i++)
if(!out[i]){mark = 1;break;}
if(mark == 1) {printf("not complete\n"); return;}
for(int i = 0; i < thnum; i++)
i == 0 ? printf("%d",out[i]) : printf(" %d",out[i]);
printf("\n");
}
char temp[20];
int flag = 0,mark = 0,num = 1;
void init()
{
num = 1; print(mark); mark = 0;flag = 0;
memset(tr,0,sizeof(tr));
}
int main()
{
while(cin.getline(s,maxm))
{
stringstream ss;
ss << s;
while(ss >> temp)
{
if(strcmp(temp,"()") == 0) {flag = 1; init();continue;}
int tlen = strlen(temp),thv = 0,stj = -1;
for(int i = 1; i < tlen; i++)
{
if(temp[i] == ','){stj = i; break;}
thv = thv*10 + temp[i] - '0';
}
int th = 1;
for(int i = stj+1; i < tlen-1; i++)
{
int thop = temp[i] == 'L' ? 0 : 1;
if(thop == 0)
{
if(tr[th].l == 0) tr[th].l = ++num;
th = tr[th].l;
}
else
{
if(tr[th].r == 0) tr[th].r = ++num;
th = tr[th].r;
}
}
if(stj + 1 == tlen-1)
{
if(tr[1].v == 0)tr[1].v = thv;
else mark = 1;
}
else
{
if(tr[th].v != 0) mark = 1;
else tr[th].v = thv;
}
}
}
return 0;
}
題意:讓你求第n個二叉樹的中序遍歷,注意這個順序是優先右邊,然後左邊。
這個時候我們可以推出一個很神奇的公式:由n個結點組成的不同二叉樹種類有:h(n) = h(0)*h(n-1) + h(1) * h(n-2) + …+h(n-1)*h(0);
好吧其實我已經知道了卡特蘭數..
都知道卡特蘭數是一個特別大的玩意,所以我們先打個表,發現5 0000 0000 的時候最多18個點。
這樣由這個卡特蘭數我們就可以推出左子樹的數量,右子樹的數量,這樣一直遞推到底,就建了一棵樹出來。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 30;
int n;
int h[20];
int sum[20],lson[maxn],rson[maxn],lid[maxn],rid[maxn];
void pre()
{
h[0] = 1; sum[0] = 1;
h[1] = 1; sum[1] = 2;
h[2] = 2; sum[2] = 4;
for(int i = 2; i <= 18; i++)
{
int ans = 0;
for(int j = 0; j < i ; j++)
ans += h[j]*h[i-j-1];
h[i] = ans;
sum[i] = sum[i-1] + ans;
}
}
int tot = 1;
void getit(int sum,int num,int id)
{
int temp = 0;
for(int i = 0; i < num; i++)
{
temp += h[i]*h[num-1-i];
if(temp > sum)
{
temp -= h[i]*h[num-1-i];
lson[id] = i;
rson[id] = num-1-i;
break;
}
}
temp = sum - temp;
int ls = temp / h[rson[id]], rs = temp % h[rson[id]];
if(lson[id] > 0) {int l = ++tot; lid[id] = l; getit(ls,lson[id],l);}
if(rson[id] > 0) {int r = ++tot; rid[id] = r; getit(rs,rson[id],r);}
}
void print(int i)
{
if(lson[i]!=0)
{ printf("("); print(lid[i]); printf(")"); }
printf("X");
if(rson[i])
{ printf("("); print(rid[i]); printf(")"); }
}
int main()
{
pre();
while(~scanf("%d",&n) && n)
{
for(int i = 0; i < 30; i++)
rson[i] = lson[i] = rid[i] = lid[i] = 0;
tot = 1;
int num = 0;
for(int i = 0; i < 19; i++)
if(sum[i] > n) {num = i; break;}
getit(n-sum[num-1],num,1);
print(1);
printf("\n");
}
return 0;
}