1.用数组建立二叉树
const int N = 40 ;
int v[ N] , l[ N] , r[ N] ;
2.完全二叉树(满二叉树)
如果按层次遍历的顺序给二叉树节点依次标号(1,2...n),
完全二叉树满足:根节点标号为i,则左孩子标号为2 * i,右孩子标号为 2 * i + 1.所以据此可以用数组建树
注意普通二叉树也可以用这个规律,但会产生大量的空节点,
会浪费大量内存。一个节点数为n的完全二叉树,只需n的空间
而普通二叉树若据此编号极端情况下最后一个节点标号会达到
2^n级别(左斜树,右斜树).
3.二叉搜索树
const int N = 40 ;
int v[ N] , l[ N] , r[ N] ;
int cnt = 0 ;
void insert ( int & root, int x)
{
if ( ! root)
{
root = ++ cnt;
v[ root] = x;
}
if ( v[ root] > x) insert ( l[ root] , x) ;
else insert ( r[ root] , x) ;
}
4.题目
后序遍历 + 中序遍历建二叉树 + 层次
#include <iostream>
#include <queue>
using namespace std;
const int N = 40 ;
int inorder[ N] , postorder[ N] ;
int l[ N] , r[ N] , p[ N] ;
queue< int > q;
void bfs ( int root)
{
q. push ( root) ;
while ( q. size ( ) )
{
int t = q. front ( ) ;
q. pop ( ) ;
cout << postorder[ t] << ' ' ;
if ( l[ t] ) q. push ( l[ t] ) ;
if ( r[ t] ) q. push ( r[ t] ) ;
}
}
int build ( int il, int ir, int pl, int pr)
{
int root = pr;
int pos = p[ postorder[ pr] ] ;
if ( il < pos) l[ root] = build ( il, pos - 1 , pl, pl + pos - 1 - il) ;
if ( pos < ir) r[ root] = build ( pos + 1 , ir, pr - ir + pos, pr - 1 ) ;
return root;
}
int main ( )
{
int n;
cin >> n;
for ( int i = 1 ; i <= n; i ++ ) cin >> postorder[ i] ;
for ( int i = 1 ; i <= n; i ++ )
{
cin >> inorder[ i] ;
p[ inorder[ i] ] = i;
}
int root = build ( 1 , n, 1 , n) ;
bfs ( root) ;
}
先序遍历 + 中序遍历 + 镜像 + 层次
#include <iostream>
#include <queue>
using namespace std;
const int N = 40 ;
int pre[ N] , in[ N] ;
int l[ N] , r[ N] , p[ N] ;
queue< int > q;
int build ( int il, int ir, int pl, int pr)
{
int root = pl;
int pos = p[ pre[ pl] ] ;
if ( il < pos) l[ root] = build ( il, pos - 1 , pl + 1 , pl + 1 + pos - 1 - il + 1 - 1 ) ;
if ( pos < ir) r[ root] = build ( pos + 1 , ir, pr - ( ir - pos - 1 + 1 ) + 1 , pr) ;
return root;
}
void rer ( int root)
{
if ( ! l[ root] && ! r[ root] ) return ;
if ( l[ root] ) rer ( l[ root] ) ;
if ( r[ root] ) rer ( r[ root] ) ;
swap ( l[ root] , r[ root] ) ;
}
void bfs ( int root)
{
q. push ( root) ;
cout << pre[ root] ;
while ( q. size ( ) )
{
int t = q. front ( ) ;
q. pop ( ) ;
if ( t != root) cout << ' ' << pre[ t] ;
if ( l[ t] ) q. push ( l[ t] ) ;
if ( r[ t] ) q. push ( r[ t] ) ;
}
}
int main ( )
{
int n;
cin >> n;
for ( int i = 1 ; i <= n; i ++ )
{
cin >> in[ i] ;
p[ in[ i] ] = i;
}
for ( int i = 1 ; i <= n; i ++ ) cin >> pre[ i] ;
int root = build ( 1 , n, 1 , n) ;
rer ( root) ;
bfs ( root) ;
}
先序 + 后序确定可能存在的二叉树数量
只有一个儿子的节点才不影响在先序和后序中遍历顺序
#include <iostream>
#include <string>
using namespace std;
int main ( )
{
string s1, s2;
cin >> s1 >> s2;
int ans = 1 ;
int n = s1. size ( ) , m = s2. size ( ) ;
for ( int i = 0 ; i < n - 1 ; i ++ )
for ( int j = 1 ; j < m; j ++ )
{
if ( s1[ i] == s2[ j] && s1[ i + 1 ] == s2[ j - 1 ] ) ans <<= 1 ;
}
cout << ans << endl;
}
后序 + 中序求先序不建树
#include <iostream>
#include <string>
using namespace std;
void dfs ( string s1, string s2)
{
if ( s1. size ( ) < 1 ) return ;
cout << s2[ s2. size ( ) - 1 ] ;
int p = 0 ;
for ( int i = 0 ; i < s1. size ( ) ; i ++ ) if ( s1[ i] == s2[ s2. size ( ) - 1 ] ) { p = i; break ; }
dfs ( s1. substr ( 0 , p) , s2. substr ( 0 , p) ) ;
dfs ( s1. substr ( p + 1 ) , s2. substr ( p, s2. size ( ) - 1 - p) ) ;
}
int main ( )
{
string s1, s2;
cin >> s1 >> s2;
dfs ( s1, s2) ;
}