昨天有同窗问到我一题关于重构二叉树的问题(link),作了一下,也作个记录吧!php
所谓二叉树的重构,就是给你前序和中序,或者中序和后序,让你还原这棵二叉树.html
注意:给出前序和后序是不能惟一肯定一棵二叉树的,证实请看这儿.node
一.给出前序和中序,重构二叉树ios
一个递归的过程:数组
当前结点的value:每一轮根据前序的第一个元素肯定当前结点值.post
左子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,左部分即为左子树的中序遍历数组.ui
右子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,右部分即为右子树的中序遍历数组.spa
左子树的前序遍历数组:pre[1 ... i] (i为左子树的中序遍历数组的个数).code
右子树的前序遍历数组:pre[i+1 ... end](i为左子树的中序遍历数组的个数).htm
构造出这5个值,继续递归求左右子树便可.
题目1:重建二叉树(剑指offer)
给出前序和中序,要你重建二叉树.
按照上面所说递归便可,详见代码:
/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
* Date : 2016-01-03-21.09
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using
namespace
std;
typedef
long
long(
LL);
typedef
unsigned
long
long(
ULL);
const
double
eps(
1e-8);
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
struct
TreeNode
{
int
val;
TreeNode
*
left;
TreeNode
*
right;
TreeNode(
int
x)
:
val(
x
),
left(
NULL
),
right(
NULL)
{}
};
class
Solution
{
public
:
vector
<
int
>
tpr;
vector
<
int
>
tin;
void
reBuild(
int
a
,
int b
,
int n
,
TreeNode
*
treeNode)
{
if(n
==
1)
// leaf node
{
treeNode
=
new
TreeNode(
tpr
[
a
]);
return ;
}
else
if(n
<=
0)
// null node
return ;
int
i
=
0;
for(;
tpr
[
a
]
!=
tin
[b
+
i
];
++
i);
TreeNode
*
lson
,
*
rson;
reBuild(
a
+
1
,b
,
i
,
lson);
reBuild(
a
+
1
+
i
,b
+
1
+
i
,n
-
i
-
1
,
rson);
treeNode
=
new
TreeNode(
tpr
[
a
]);
treeNode
->
left
=
lson;
treeNode
->
right
=
rson;
}
struct
TreeNode
*
reConstructBinaryTree(
vector
<
int
>
pre
,
vector
<
int
>
in)
{
tpr
.
clear();
tin
.
clear();
for(
int
i
=
0;
i
<
pre
.
size();
++
i)
tpr
.
push_back(
pre
[
i
]);
for(
int
i
=
0;
i
<
in
.
size();
++
i)
tin
.
push_back(
in
[
i
]);
TreeNode
*
root;
int n
=
pre
.
size();
reBuild(
0
,
0
,n
,
root);
return
root;
}
};
void
DFS(
TreeNode
*
root)
{
if(
root)
{
cout
<<(
root
->
val)
<<
" ";
}
else
return ;
if(
root
->
left)
DFS(
root
->
left);
if(
root
->
right)
DFS(
root
->
right);
}
int
main()
{
freopen(
"D:
\\
Desktop
\\
in.txt"
,
"r"
,
stdin);
int n;
vector
<
int
>
pre;
vector
<
int
>
in;
while(
cin
>>n)
{
pre
.
clear();
in
.
clear();
for(
int
i
=
0;
i
<n;
++
i)
{
int
tmp;
cin
>>
tmp;
pre
.
push_back(
tmp);
}
for(
int
i
=
0;
i
<n;
++
i)
{
int
tmp;
cin
>>
tmp;
in
.
push_back(
tmp);
}
Solution
a;
TreeNode
*
root
=
a
.
reConstructBinaryTree(
pre
,
in);
DFS(
root);
}
return
0;
}
题目2:HDU 1710 Binary Tree Traversals
方法一:也很简单,根据上面说的方法递归建树,而后按照后序访问输出便可.
/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
* Date : 2016-01-04-18.01
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using
namespace
std;
typedef
long
long(
LL);
typedef
unsigned
long
long(
ULL);
const
double
eps(
1e-8);
int n;
vector
<
int
>
pr;
vector
<
int
>
in;
struct
TreeNode
{
int
val;
TreeNode
*
left
,
*
right;
TreeNode(
int
v)
:
val(
v
),
left(
NULL
),
right(
NULL
){}
};
TreeNode
*
reBuildBinaryTree(
vector
<
int
>
pr
,
vector
<
int
>
in)
{
if(
pr
.
size()
==
0 ||
in
.
size()
==
0)
return
NULL;
int
root
=
pr
[
0
];
TreeNode
*
node
=
new
TreeNode(
root);
vector
<
int
>
prLeft
,
prRight
,
inLeft
,
inRight;
int
i
=
0;
for(;
pr
[
0
]
!=
in
[
i
];
++
i);
for(
int
j
=
0;
j
!=
i;
++
j)
inLeft
.
push_back(
in
[
j
]);
for(
int
j
=
i
+
1;
j
<
in
.
size();
++
j)
inRight
.
push_back(
in
[
j
]);
for(
int
j
=
1;
j
<
i
+
1;
++
j)
prLeft
.
push_back(
pr
[
j
]);
for(
int
j
=
i
+
1;
j
<
pr
.
size();
++
j)
prRight
.
push_back(
pr
[
j
]);
node
->
left
=
reBuildBinaryTree(
prLeft
,
inLeft);
node
->
right
=
reBuildBinaryTree(
prRight
,
inRight);
return
node;
}
vector
<
int
>
po;
void
getPostOrder(
TreeNode
*
root
,
bool
flag)
{
if(
root
->
left)
getPostOrder(
root
->
left
,
0);
if(
root
->
right)
getPostOrder(
root
->
right
,
0);
po
.
push_back(
root
->
val);
}
int
main()
{
while(
cin
>>n)
{
int
tmp;
pr
.
clear();
in
.
clear();
po
.
clear();
for(
int
i
=
0;
i
<n;
++
i)
{
cin
>>
tmp;
pr
.
push_back(
tmp);
}
for(
int
i
=
0;
i
<n;
++
i)
{
cin
>>
tmp;
in
.
push_back(
tmp);
}
TreeNode
*
root
=
reBuildBinaryTree(
pr
,
in);
getPostOrder(
root
,
1);
for(
int
i
=
0;
i
<n;
++
i)
{
if(
i
<n
-
1)
cout
<<
po
[
i
]
<<
" ";
else
cout
<<
po
[
i
]
<<
endl;
}
}
return
0;
}
方法二:因为题目没让重构二叉树,只让输出后序访问的顺序,所以可直接访问输出.
/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
* Date : 2016-01-04-20.09
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using
namespace
std;
typedef
long
long(
LL);
typedef
unsigned
long
long(
ULL);
const
double
eps(
1e-8);
int n;
vector
<
int
>
pr;
// pre Order
vector
<
int
>
in;
// in Order
vector
<
int
>
po;
// post Order
void
getPostOrder(
int
a
,
int b
,
int n
,
bool
flag)
{
if(n
==
1)
{
po
.
push_back(
pr
[
a
]);
return;
}
else
if(n
<=
0)
return;
int
i
=
0;
for(;
pr
[
a
]
!=
in
[b
+
i
];
++
i);
getPostOrder(
a
+
1
,b
,
i
,
false);
getPostOrder(
a
+
i
+
1
,b
+
i
+
1
,n
-
i
-
1
,
false);
po
.
push_back(
pr
[
a
]);
}
int
main()
{
while(
cin
>>n)
{
pr
.
clear();
in
.
clear();
po
.
clear();
for(
int
i
=
0;
i
<n;
++
i)
{
int
tmp;
cin
>>
tmp;
pr
.
push_back(
tmp);
}
for(
int
i
=
0;
i
<n;
++
i)
{
int
tmp;
cin
>>
tmp;
in
.
push_back(
tmp);
}
getPostOrder(
0
,
0
,n
,
true);
for(
int
i
=
0;
i
<n;
++
i)
{
if(
i
<n
-
1)
cout
<<
po
[
i
]
<<
" ";
else
cout
<<
po
[
i
]
<<
endl;
}
}
return
0;
}
二.给出后序和中序,重构二叉树
一个递归的过程:
当前结点的value:每一轮根据前序的最后一个元素肯定当前结点值.
左子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,左部分即为左子树的中序遍历数组.
右子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,右部分即为右子树的中序遍历数组.
左子树的前序遍历数组:pre[0 ... i-1] (i为左子树的中序遍历数组的个数).
右子树的前序遍历数组:pre[i ... end-1](i为左子树的中序遍历数组的个数).
构造出这5个值,继续递归求左右子树便可.
红色部分标出的是和上面的不一样点,其他都相同.
/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
* Date : 2016-01-04-22.07
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using
namespace
std;
typedef
long
long(
LL);
typedef
unsigned
long
long(
ULL);
const
double
eps(
1e-8);
int n;
vector
<
int
>
po;
vector
<
int
>
in;
struct
TreeNode
{
int
val;
TreeNode
*
left
,
*
right;
TreeNode(
int
v)
:
val(
v
),
left(
NULL
),
right(
NULL
){}
};
TreeNode
*
reBuildBinaryTree(
vector
<
int
>
po
,
vector
<
int
>
in)
{
if(
po
.
size()
==
0 ||
in
.
size()
==
0)
return
NULL;
int
root
=
po
[
po
.
size()
-
1
];
TreeNode
*
node
=
new
TreeNode(
root);
vector
<
int
>
poLeft
,
poRight
,
inLeft
,
inRight;
int
i
=
0;
for(;
in
[
i
]
!=
root;
++
i);
for(
int
j
=
0;
j
<
i;
++
j)
inLeft
.
push_back(
in
[
j
]);
for(
int
j
=
i
+
1;
j
<
in
.
size();
++
j)
inRight
.
push_back(
in
[
j
]);
for(
int
j
=
0;
j
<
i;
++
j)
poLeft
.
push_back(
po
[
j
]);
for(
int
j
=
i;
j
<
po
.
size()
-
1;
++
j)
poRight
.
push_back(
po
[
j
]);
node
->
left
=
reBuildBinaryTree(
poLeft
,
inLeft);
node
->
right
=
reBuildBinaryTree(
poRight
,
inRight);
return
node;
}
void
print_BFS(
TreeNode
*
root)
{
queue
<
TreeNode
*>
q;
q
.
push(
root);
while(
!
q
.
empty())
{
TreeNode
*
now
=
q
.
front();
q
.
pop();
cout
<<(
now
->
val)
<<
" ";
if(
now
->
left)
q
.
push(
now
->
left);
if(
now
->
right)
q
.
push(
now
->
right);
}
}
int
main()
{
// test demo
int
a
[]
=
{
7
,
4
,
2
,
5
,
8
,
6
,
3
,
1
};
int b
[]
=
{
4
,
7
,
2
,
1
,
5
,
3
,
8
,
6
};
po
.
clear();
in
.
clear();
for(
int
i
=
0;
i
<
8;
++
i)
{
po
.
push_back(
a
[
i
]);
in
.
push_back(b
[
i
]);
}
TreeNode
*
root
=
reBuildBinaryTree(
po
,
in);
print_BFS(
root);
return
0;
}