1. 求以孩子兄弟表示法存储的森林的叶子结点数。
算法思想:当森林(树)以孩子兄弟表示法存储时,若结点没有孩子,则它必是叶子,当森林(树)转化为以孩子兄弟表示法存储的二叉树时,如果某个结点的左孩子为NULL,则该结点就是原森林(树)的叶子结点。
int Leaves ( CSTree t)
{
static int count = 0 ;
if ( t == NULL ) return 0 ;
else
{
if ( t-> firstchild == NULL )
{
printf ( "%c " , t-> data) ;
count++ ;
}
Leaves ( t-> firstchild) ;
Leaves ( t-> nextsibling) ;
}
return count;
}
运行结果
2. 以孩子兄弟链表为存储结构,求树的深度。
算法思想:采用递归算法,若树为空,高度为零;否则,高度为第一子女树高度加1和兄弟子树高度的大者。 其非递归算法使用队列,逐层遍历取得树的高度。
int Height ( CSTree t)
{
int h1, h2;
if ( t == NULL ) return 0 ;
else
{
h1 = Height ( t-> firstchild) ;
h2 = Height ( t-> nextsibling) ;
if ( h1 + 1 > h2) return h1 + 1 ;
else return h2;
}
}
运行结果
3. 已知一棵树的层次序列及每个结点的度,构造此树的孩子—兄弟链表。
本题与树的层次序列有关。可设立一个辅助数组pointer[ ]存储新建树的各结点的地址,再根据层次序列与每个结点的度,逐个链接结点。
# define MaxNode 15
void CreateCSTree ( CSTree& t, ElemType e[ ] , int degree[ ] , int n)
{
CSNode* pointer = new CSNode[ MaxNode] ;
int i, j, d, k = 0 ;
for ( i = 0 ; i < n; i++ )
{
pointer[ i] -> data = e[ i] ;
pointer[ i] -> firstchild = pointer[ i] -> nextsibling = NULL ;
}
for ( i = 0 ; i < n; i++ )
{
d = degree[ i] ;
if ( d != 0 )
{
k++ ;
pointer[ i] -> firstchild = pointer[ k] ;
for ( j = 2 ; j <= d; j++ )
{
k++ ;
pointer[ k - 1 ] -> nextsibling = pointer[ k] ;
}
}
}
T = pointer[ 0 ] ;
delete[ ] pointer;
}
4. 判断给定的二叉树是否是二叉排序树。
bool isBST ( BiTree t)
{
if ( t != NULL )
{
if ( t-> lchild != NULL )
{
if ( t-> lchild-> data > t-> data) return false;
else if ( t-> rchild != NULL )
{
if ( t-> rchild-> data < t-> data) return false;
}
}
isBST ( t-> lchild) ;
isBST ( t-> rchild) ;
}
else return true;
}
运行结果
5. 求出指定结点在给定二叉排序树中的层次。
int Level ( BiTree t, ElemType key)
{
static int count = 1 ;
if ( t != NULL )
{
if ( t-> data == key) return count;
else if ( t-> data > key)
{
Level ( t-> lchild, key) ;
count++ ;
}
else
{
Level ( t-> rchild, key) ;
count++ ;
}
}
return count;
}
运行结果
6. 判断二叉树是否是平衡二叉树。
void isAVL ( BiTree t, int & balance, int & h)
{
int bl = 0 , br = 0 , hl = 0 , hr = 0 ;
if ( t == NULL )
{
h = 0 ;
balance = 1 ;
}
else if ( t-> lchild == NULL && t-> rchild == NULL )
{
h = 1 ;
balance = 1 ;
}
else
{
isAVL ( t-> lchild, bl, hl) ;
isAVL ( t-> rchild, br, hr) ;
h = ( hl > hr ? hl : hr) + 1 ;
if ( abs ( hl - hr) < 2 ) balance = bl && br;
else balance = 0 ;
}
}
运行结果
7. 求出给定二叉排序树中最小和最大的关键字。
void Min_MaxKey ( BiTree t, ElemType & min, ElemType & max)
{
BiTNode* p, * q;
if ( t-> lchild == NULL && t-> rchild == NULL ) min= t-> data;
else
{
p = q = t;
while ( p-> rchild != NULL ) p = p-> rchild;
max = p-> data;
while ( q-> lchild != NULL ) q = q-> lchild;
min = q-> data;
}
}
运行结果
8. 从大到小输出二叉排序树中所有值不小于k的关键字。
void OutPut ( BiTree t, ElemType key)
{
if ( t == NULL ) return ;
else
{
if ( t-> rchild != NULL ) OutPut ( t-> rchild, key) ;
if ( t-> data >= key) printf ( "%d " , t-> data) ;
if ( t-> lchild != NULL ) OutPut ( t-> lchild, key) ;
}
}
运行结果
9. 编写一个递归算法,在一棵有m个结点的、随机建立起来的二叉排序树上查找第k(1≤k≤m)小的元素,并返回指向该结点的指针。要求算法的平均时间复杂度为
O
(
l
o
g
2
n
O(log_2^n
O ( l o g 2 n )。二叉排序树的每个结点中除data,lchild,rchild等数据成员外,增加一个 count成员,保存以该结点为根的子树上的结点个数。
算法思想:设二叉排序树的根结点为*t,根据结点存储的信息,有以下几种情况: t->lchild为空时,情况如下: 1)若t->rchild非空且k==1,则*t即为第k小的元素,查找成功。 2)若t->rchild非空且k!=1,则第k小的元素必在*t的右子树。 若t->lchild非空时,情况如下: 1)t->lchild->count==k-1,*t即为第k小的元素,查找成功。 2)t->lchild->count>k-1,第k小的元素必在*t的左子树,继续到*t的左子树中查找。 3)t->lchild->count<k-1,第k小的元素必在右子树,继续搜索右子树,寻找第k(t->lchild->count+1)小的元素。 对左右子树的搜索采用相同的规则。
BiTNode* Search_Small ( BiTNode* t, int k)
{
if ( k< 1 || k> t-> count) return NULL ;
if ( t-> lchild == NULL )
{
if ( k == 1 ) return t;
else return Search_Small ( t, k - 1 ) ;
}
else
{
if ( t-> lchild-> count == k - 1 ) return t;
if ( t-> lchild-> count > k - 1 ) return Search_Small ( t-> lchild, k) ;
if ( t-> lchild-> count < k - 1 ) return Search_Small ( t-> rchild, k - ( t-> lchild-> count + 1 ) ) ;
}
}
10. 假设二叉排序树bt中所有的关键字是由整数构成的,为了查找某关键字k,会得到一个查找序列。判断一个序列(存放在a数组中)是否是从bt中搜索关键字k的序列。
算法思想:设查找序列a中有n个关键字,如果查找成功,a[n-1]应等于k。用i扫描a数组(初值为0),p用于在二叉排序树bt中查找(p的初值指向根结点),每查找一层,比较该层的结点关键字pー>key是否等于a[i],若不相等,表示a不是bt中查找关键字k的序列,返回false;否则继续查找下去。若一直未找到关键字k,则p最后必为NULL,表示a不是查找序列,返回false;否则表示在bt中查找到k,p指向该结点,表示a是查找序列,返回true。
bool Findseq ( BSTNode* bt, int k, int a[ ] , int n)
{
BSTNode* p = bt;
int i = 0 ;
if ( a[ n - 1 ] != k) return false;
while ( i < n && p != NULL )
{
if ( p. key != a[ i] ) return false;
if ( k < p. key) p = p. lchild;
else if ( k > p. key) p = p. rchild;
i++ ;
}
if ( p != NULL ) return true;
else return false;
}
运行结果
11. 对于二叉排序树bt设计一个算法,输出在该树中查找某个关键字k所经过的路径。
算法思想:设计的算法为SearchPath(BSTNode *bt, KeyType k, KeyType path[ ],intd),它输出二叉排序树bt中査找关键字k的查找路径。使用path数组存储经过的结点,d表示path中最后关键字的下标,初始值为-1。当找到所要找的结点时,输出path数组中的元素值,从而以根结点到当前结点输出路径。
void SearchPath ( BSTNode* bt, ElemType k, ElemType path[ ] , int d)
{
if ( bt == NULL ) return ;
else if ( k == bt-> data)
{
d++ ;
path[ d] = bt-> data;
for ( int i = 0 ; i <= d; i++ ) printf ( "%2d " , path[ i] ) ;
printf ( "\n" ) ;
}
else
{
d++ ;
path[ d] = bt-> data;
if ( k < bt-> data) SearchPath ( bt-> lchild, k, path, d) ;
else SearchPath ( bt-> rchild, k, path, d) ;
}
}
运行结果
12. 假设二叉树采用二叉链存储结构,设计一个算法输出值为x的结点的所有祖先。
根据二叉树中祖先的定义可知,若结点p的左孩子或右孩子是结点q,则结点p是结点q的祖先;若结点p的左孩子或右孩子是q结点的祖先;则结点也是结点q的祖先。 设f(b,x)表示结点b是否为值是x的结点的祖先,若结点b是值为的结点的祖先f(b,x),返回true;否则f(b,x)返回false。当f(b,x)为true时,输出结点b的值。求值为x的结点的所有祖先的递归模型f(b,x)如下:
{
f
(
b
,
x
)
=
f
a
l
s
e
若
b
=
N
U
L
L
f
(
b
,
x
)
=
t
r
u
e
,
并
输
出
b
−
>
d
a
t
a
若
结
点
b
的
左
孩
子
或
右
孩
子
的
d
a
t
a
域
为
x
f
(
b
,
x
)
=
t
r
u
e
,
并
输
出
b
−
>
d
a
t
a
若
f
(
b
−
>
l
c
h
i
l
d
,
x
)
为
t
r
u
e
或
f
(
b
−
>
r
c
h
i
l
d
,
x
)
为
t
r
u
e
f
(
b
,
x
)
=
f
a
l
s
e
其
他
情
况
\begin{cases} f(b, x)=false\;\;\;\;\;若b=NULL\\ f(b,x)=true,并输出b->data\;\;\;\;\;若结点b的左孩子或右孩子的data域为x\\ f(b,x)=true,并输出b->data\;\;\;\;\;若f(b->lchild,x)为true或f(b-> rchild,x)为true\\ f(b, x)= false\;\;\;\;\;其他情况 \end{cases}
⎩ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎧ f ( b , x ) = f a l s e 若 b = N U L L f ( b , x ) = t r u e , 并 输 出 b − > d a t a 若 结 点 b 的 左 孩 子 或 右 孩 子 的 d a t a 域 为 x f ( b , x ) = t r u e , 并 输 出 b − > d a t a 若 f ( b − > l c h i l d , x ) 为 t r u e 或 f ( b − > r c h i l d , x ) 为 t r u e f ( b , x ) = f a l s e 其 他 情 况
bool Ancestor ( BiTNode* t, ElemType x)
{
if ( t == NULL ) return false;
else if ( t-> lchild != NULL && t-> lchild-> data == x || t-> rchild != NULL && t-> rchild-> data == x)
{
printf ( "%c " , t-> data) ;
return true;
}
else if ( Ancestor ( t-> lchild, x) || Ancestor ( t-> rchild, x) )
{
printf ( "%c " , t-> data) ;
return true;
}
else return false;
}
运行结果