昨天有同窗問到我一題關於重構二叉樹的問題(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;
}