第六章
- 一、判别两棵二叉树是否相似
- 二、编写递归算法,求对二叉树T先序遍历时第k个访问的结点的值
- 三、编写递归算法,计算二叉树T中叶子结点的数目
- 四、试利用栈及其基本操作写出二叉树T的非递归的先序遍历算法
- 五、试利用栈及其基本操作写出二叉树T的非递归的后序遍历算法
- 六、二叉树采用三叉链表的存储结构,试编写不借助栈的非递归中序遍历算法
- 七、编写不用栈辅助的二叉树非递归后序遍历算法
- 八、编写递归算法,将二叉树中所有结点的左、右子树相互交换
- 九、编写递归算法:求二叉树中以元素值为x的结点为根的子树的深度
- 十、 编写递归算法:对于二叉树中每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间
- 十一、编写复制一棵二叉树的递归算法
- 十二、编写算法判别给定二叉树是否为完全二叉树
- 十三、试编写一个二叉排序树的判定算法
- 十四、 编写递归算法,从大到小输出给定二叉排序树中所有关键字不小于x的数据元素
- 十五、试写一非递归算法,在二叉查找树T中插入元素e
- 十六、试编写算法,求二叉树T中结点a和b的最近共同祖先
- 十七、求树中第k小的结点的位置
- 十八、 假设二叉排序树T的每个结点的平衡因子域bf当前均为0。试编写算法,求二叉排序树T的深度,并为每个结点的bf域赋予正确的平衡因子值
- 十九、编写平衡二叉排序树的右平衡处理算法
一、判别两棵二叉树是否相似
【题目】若两棵二叉树T1和T2皆为空,或者皆不空且T1的左、右子树和T2的左、右子树分别相似,则称二叉树T1和T2相似。试编写算法,判别给定的两棵二叉树是否相似。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
// 如果T1和T2相似,则返回TRUE;否则返回FALSE
Status Similar(BiTree T1, BiTree T2);
#include "allinclude.h" //DO NOT edit this line
Status Similar(BiTree T1, BiTree T2){
// Add your code here
//递归
if(!T1&&!T2) return TRUE;
if(T1&&T2){
if(Similar(T1->lchild,T2->lchild)&&Similar(T1->rchild,T2->rchild)) return TRUE;
}
return FALSE;
}
二、编写递归算法,求对二叉树T先序遍历时第k个访问的结点的值
【题目】编写递归算法,求对二叉树T先序遍历时第k个访问的结点的值。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
TElemType PreOrderK(BiTree T, int k);
/* 求对二叉树T先序遍历时第k个访问的结点的值。/
/ 若失败,则返回’#’ */
#include "allinclude.h" //DO NOT edit this line
TElemType PreOrder(BiTree T, int &rek){//原题接口中参数k没有取地址符号&,递归无法实现,需要再写一个函数
TElemType re = '#';
if(!T||rek < 1) return '#';
if(rek == 1) return T->data;
rek--;
if(T->lchild)
re = PreOrder(T->lchild,rek);//不能写rek-1
if(T->rchild && re == '#')
re = PreOrder(T->rchild,rek);
return re;
}
TElemType PreOrderK(BiTree T, int k){
return PreOrder(T,k);
}
三、编写递归算法,计算二叉树T中叶子结点的数目
【题目】编写递归算法,计算二叉树T中叶子结点的数目。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
int Leaves(BiTree T);
/* 计算二叉树T中叶子结点的数目 */
#include "allinclude.h" //DO NOT edit this line
int Leaves(BiTree T){
// Add your code here
if(!T) return 0;
//只有根,就是一片树叶
if(!T->lchild&&!T->rchild) return 1;
return Leaves(T->lchild)+Leaves(T->rchild);
}
四、试利用栈及其基本操作写出二叉树T的非递归的先序遍历算法
【题目】试利用栈及其基本操作写出二叉树T的非递归的先序遍历算法。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;
可用栈类型Stack的相关定义:
typedef BiTree SElemType; // 栈的元素类型
Status InitStack(Stack &S);
Status StackEmpty(Stack S);
Status Push(Stack &S, SElemType e);
Status Pop(Stack &S, SElemType &e);
Status GetTop(Stack S, SElemType &e);
要求实现下列函数:
void PreOrder(BiTree T, void (visit)(TElemType));
/ 使用栈,非递归先序遍历二叉树T, /
/ 对每个结点的元素域data调用函数visit */
#include "allinclude.h" //DO NOT edit this line
void PreOrder(BiTree T, Status (*visit)(TElemType)){
// Add your code here
//创建栈S
Stack S;
InitStack(S);
BiTree p;
p = T;
while(p){
visit(p->data);
if(p->rchild) Push(S,p->rchild);
if(p->lchild) p = p->lchild;
else if(!StackEmpty(S)) Pop(S,p);
else p = NULL;
}
}
五、试利用栈及其基本操作写出二叉树T的非递归的后序遍历算法
【题目】试利用栈及其基本操作写出二叉树T的非递归的后序遍历算法(提示:为分辨后序遍历时两次进栈的不同返回点,需在指针进栈时同时将一个标志进栈)。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;
可用栈类型Stack的相关定义:
typedef struct {
struct BiTNode *ptr; // 二叉树结点的指针类型
int tag; // 0…1
} SElemType; // 栈的元素类型
Status InitStack(Stack &S);
Status StackEmpty(Stack S);
Status Push(Stack &S, SElemType e);
Status Pop(Stack &S, SElemType &e);
Status GetTop(Stack S, SElemType &e);
要求实现下列函数:
void PostOrder(BiTree T, void (visit)(TElemType));
/ 使用栈,非递归后序遍历二叉树T, /
/ 对每个结点的元素域data调用函数visit */
#include "allinclude.h" //DO NOT edit this line
void PostOrder(BiTree T, Status (*visit)(TElemType)){
// Add your code here
if(!T) return ;
//建一个栈
Stack s;
InitStack(s);
//建立栈元素
SElemType n;
n.ptr = T;
n.tag =0;//tag为012,分别代表VLR
//先把根结点入栈
Push(s,n);
while(!StackEmpty(s)){
//先出栈
Pop(s,n);
if(n.tag == 0){
n.tag = 1;
Push(s,n);
if(n.ptr->lchild){
n.ptr = n.ptr->lchild;
n.tag = 0;
Push(s,n);
}
}else if(n.tag == 1){
n.tag = 2;
Push(s,n);
if(n.ptr->rchild){
n.ptr = n.ptr->rchild;
n.tag = 0;
Push(s,n);
}
}else visit(n.ptr->data);
}
}
六、二叉树采用三叉链表的存储结构,试编写不借助栈的非递归中序遍历算法
【题目】二叉树采用三叉链表的存储结构,试编写不借助栈的非递归中序遍历算法。
三叉链表类型定义:
typedef struct TriTNode {
TElemType data;
struct TriTNode *parent, *lchild, *rchild;
} TriTNode, *TriTree;
要求实现以下函数:
void InOrder(TriTree PT, void (visit)(TElemType));
/ 不使用栈,非递归中序遍历二叉树PT, /
/ 对每个结点的元素域data调用函数visit */
#include "allinclude.h" //DO NOT edit this line
void InOrder(TriTree PT, Status (*visit)(TElemType)){
// Add your code here
if(!PT) return ;
TriTree p;
p = PT;
//找到最左子树
while(p->lchild) p = p->lchild;
while(p){
visit(p->data);
if(!p->parent&&!p->rchild) break;
if(p->rchild){
p = p->rchild;
//遍历右子树的左子树
while(p->lchild) p = p->lchild;
}
else if(p->parent->lchild == p) p = p->parent;
else{
p = p->parent;
while(p->parent&&p->parent->rchild == p){
p = p->parent;
}
p = p->parent;
}
}
}
七、编写不用栈辅助的二叉树非递归后序遍历算法
【题目】假设在三叉链表的结点中增设一个标志域(mark取值0,1或2)以区分在遍历过程中到达该结点时应继续向左或向右或访问该结点。试以此存储结构编写不用栈辅助的二叉树非递归后序遍历算法。
带标志域的三叉链表类型定义:
typedef struct TriTNode {
TElemType data;
struct TriTNode *lchild, *rchild, *parent;
int mark; // 标志域
} TriTNode, *TriTree;
要求实现以下函数:
void PostOrder(TriTree T, Status (visit)(TElemType));
/ 不使用栈,非递归后序遍历二叉树T, /
/ 对每个结点的元素域data调用函数visit */
#include "allinclude.h" //DO NOT edit this line
void PostOrder(TriTree T, Status (*visit)(TElemType)){
// Add your code here
TriTree p = T;
while(p){
//如果当前访问结点标志为0,则依次把左子树的标志改为1,直到最左子树
while(p->mark == 0){
p->mark = 1;
if(p->lchild) p = p->lchild;
}
//如果当前结点标志为1,则表示其左子树已被访问,先将其标志依次改为2,等待右子树访问完后再访问自己
while(p->mark == 1){
p->mark = 2;
if(p->rchild) p = p->rchild;
}
//如果当前结点为2,则进行访问,并返回双亲结点
if(p->mark == 2){
visit(p->data);
p = p->parent;
}
}
}
八、编写递归算法,将二叉树中所有结点的左、右子树相互交换
【题目】编写递归算法,将二叉树中所有结点的左、右子树相互交换。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
void ExchangeSubTree(BiTree &T);
/* 将二叉树中所有结点的左、右子树相互交换 */
#include "allinclude.h" //DO NOT edit this line
void ExchangeSubTree(BiTree &T){
// Add your code here
if(!T) return;
BiTree p;
//如果左右孩子都是空就不用交换了
if(T->lchild||T->rchild){
p = T->lchild;
T->lchild = T->rchild;
T->rchild = p;
}
ExchangeSubTree(T->lchild);
ExchangeSubTree(T->rchild);
}
九、编写递归算法:求二叉树中以元素值为x的结点为根的子树的深度
【题目】编写递归算法:求二叉树中以元素值为x的结点为根的子树的深度。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
int Depthx(BiTree T, TElemType x);
/* 求二叉树中以值为x的结点为根的子树深度 */
#include "allinclude.h" //DO NOT edit this line
int Depthx(BiTree T, TElemType x){
// Add your code here
if(!T) return 0;
if(T){
int lt,rt;
if(T->data == x){
//要加上两个if条件,不然T->lchild为空时,T->lchild->data不存在,会报错
if(!T->lchild) lt = 0;
else lt = Depthx(T->lchild,T->lchild->data);
if(!T->rchild) rt = 0;
else rt = Depthx(T->rchild,T->rchild->data);
return 1+(lt>rt?lt:rt);
}else{
lt = Depthx(T->lchild,x);
rt = Depthx(T->rchild,x);
return lt>rt?lt:rt;
}
}
}
十、 编写递归算法:对于二叉树中每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间
【题目】编写递归算法:对于二叉树中每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
void ReleaseX(BiTree &T, char x);
/* 对于二叉树中每一个元素值为x的结点, /
/ 删去以它为根的子树,并释放相应的空间 */
#include "allinclude.h" //DO NOT edit this line
void ReleaseX(BiTree &T, char x){
// Add your code here
if(!T) return;
if(T->data == x){
if(T->lchild)
ReleaseX(T->lchild,T->lchild->data);
if(T->rchild)
ReleaseX(T->rchild,T->rchild->data);
//free(T);
T = NULL;
}else{
ReleaseX(T->lchild,x);
ReleaseX(T->rchild,x);
}
}
十一、编写复制一棵二叉树的递归算法
【题目】编写复制一棵二叉树的递归算法。
二叉链表类型定义:
typedef char TElemType; // 设二叉树的元素为char类型
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
要求实现下列函数:
void CopyBiTree(BiTree T, BiTree &TT);
/* 递归复制二叉树T得到TT */
#include "allinclude.h" //DO NOT edit this line
void CopyBiTree(BiTree T, BiTree &TT){
// Add your code here
if(!T) TT = NULL;
else{
//每次运行到这都要开拓新的空间
TT = (BiTree)malloc(sizeof(BiTNode));
TT->data = T->data;
CopyBiTree(T->lchild,TT->lchild);
CopyBiTree(T->rchild,TT->rchild);
}
}
十二、编写算法判别给定二叉树是否为完全二叉树
【题目】编写算法判别给定二叉树是否为完全二叉树。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
可用队列类型Queue的相关定义:
typedef BiTree QElemType; // 设队列元素为二叉树的指针类型
Status InitQueue(Queue &Q);
Status EnQueue(Queue &Q, QElemType e);
Status DeQueue(Queue &Q, QElemType &e);
Status GetHead(Queue Q, QElemType &e);
Status QueueEmpty(Queue Q);
要求实现下列函数:
Status CompleteBiTree(BiTree T);
/* 判别二叉树T是否为完全二叉树 */
#include "allinclude.h" //DO NOT edit this line
Status CompleteBiTree(BiTree T){
// Add your code here
if(!T) return TRUE;
int flag = 0;
Queue Q;
BiTree p = T;
//构建一个空队列
InitQueue(Q);
//根结点入队
EnQueue(Q,p);
while(DeQueue(Q,p)){
if(!p) flag = 1;
else if(flag) return FALSE;
else{
EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild);
}
}
return TRUE;
}
十三、试编写一个二叉排序树的判定算法
【题目】试编写一个二叉排序树的判定算法。
二叉排序树的类型BSTree定义如下:
typedef struct {
KeyType key;
… … // 其他数据域
} TElemType;
typedef struct BiTNode {
TElemType data;
struct BSTNode *lchild, *rchild;
}BSTNode, *BSTree;
实现下列函数:
Status IsBSTree(BSTree T);
/* 判别二叉树T是否为二叉排序树。/
/ 若是,则返回TRUE,否则FALSE */
#include "allinclude.h" //DO NOT edit this line
Status IsBSTree(BSTree T){
// Add your code here
if(!T||(!T->lchild&&!T->rchild)) return TRUE;
if(T->lchild)
if(T->lchild->data.key >= T->data.key) return FALSE;
if(T->rchild)
if(T->rchild->data.key <= T->data.key) return FALSE;
if(IsBSTree(T->lchild)) return IsBSTree(T->rchild);
return FALSE;
}
十四、 编写递归算法,从大到小输出给定二叉排序树中所有关键字不小于x的数据元素
【题目】编写递归算法,从大到小输出给定二叉排序树中所有关键字不小于x的数据元素。
二叉排序树的类型BSTree定义如下:
typedef struct {
KeyType key;
… … // 其他数据域
} TElemType;
typedef struct BSTNode {
TElemType data;
struct BSTNode *lchild,*rchild;
}BSTNode, *BSTree;
实现下列函数:
void OrderOut(BSTree T, KeyType k, void(visit)(TElemType));
/ 调用visit(T->data)输出 */
#include "allinclude.h" //DO NOT edit this line
void OrderOut(BSTree T, KeyType k, void(*visit)(TElemType)){
// Add your code here
if(!T) return;
//大的在右边
OrderOut(T->rchild,k,visit);
if(T->data.key >= k){
visit(T->data);
OrderOut(T->lchild,k,visit);
}
}
十五、试写一非递归算法,在二叉查找树T中插入元素e
【题目】试写一非递归算法,在二叉查找树T中插入元素e。
二叉查找树的类型BSTree定义如下:
typedef struct {
KeyType key;
… … // 其他数据域
} TElemType;
typedef struct BSTNode {
TElemType data;
struct BSTNode *lchild,*rchild;
} BSTNode, *BSTree;
实现下列函数:
Status InsertBST_I(BSTree &T, TElemType k);
/* 在二叉查找树T中插入元素e的非递归算法 */
#include "allinclude.h" //DO NOT edit this line
Status InsertBST_I(BSTree &T, TElemType k){
// Add your code here
BSTree s,p = T;
s = (BSTree)malloc(sizeof(BSTNode));
if(!s) return OVERFLOW;
s->data = k;
s->lchild = NULL;
s->rchild = NULL;
while(T){
if(p->data.key == k.key) return OVERFLOW;
if(p->data.key > k.key){
if(p->lchild) p = p->lchild;
else p->lchild = s;
}else{
if(p->rchild) p = p->rchild;
else p->rchild = s;
}
}
}
十六、试编写算法,求二叉树T中结点a和b的最近共同祖先
【题目】试编写算法,求二叉树T中结点a和b的最近共同祖先。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;
可用栈类型Stack的相关定义:
typedef struct {
BiTNode *ptr; // 二叉树结点的指针类型
int tag; // 0…1
} SElemType; // 栈的元素类型
Status InitStack(Stack &S);
Status StackEmpty(Stack S);
int StackLength(SqStack S);
Status Push(Stack &S, SElemType e);
Status Pop(Stack &S, SElemType &e);
Status GetTop(Stack S, SElemType &e);
要求实现下列函数:
BiTree CommAncestor(BiTree T, TElemType a, TElemType b);
/* 求二叉树T中结点a和b的最近共同祖先 */
#include "allinclude.h" //DO NOT edit this line
Status Get(BiTree t, TElemType v, Stack &s){//构建一个寻找结点位置的函数
if(!t) return ERROR;
SElemType e;
e.ptr = t;
if(t->data == v){
Push(s,e);
return OK;
}
if(OK == Get(t->lchild,v,s)){
Push(s,e);
return OK;
}
if(OK == Get(t->rchild,v,s)){
Push(s,e);
return OK;
}
return ERROR;
}
BiTree CommAncestor(BiTree T, TElemType a, TElemType b){
// Add your code here
if(!T) return NULL;
//构建两个栈
Stack Sa,Sb;
InitStack(Sa);
InitStack(Sb);
//如果找不到a,b两个结点
if(!Get(T,a,Sa)||!Get(T,b,Sb)) return NULL;
SElemType e1,e2,E1,E2;
//先把两个栈顶元素取出来
Pop(Sa,E1);
Pop(Sb,E2);
while(!StackEmpty(Sa)&&!StackEmpty(Sb)){
//先把刚取出来的元素记住
e1 = E1;
e2 = E2;
//再分别取出下一个栈顶元素
if(!Pop(Sa,E1)||!Pop(Sb,E2)||E1.ptr->data != E2.ptr->data||E1.ptr->data == a||E2.ptr->data == b)
return e1.ptr;
}
return NULL;
}
十七、求树中第k小的结点的位置
【题目】在二叉排序树的每个结点中增设一个lsize域,其值为该结点的左子树中的结点数加1。试编写时间复杂度为O(logn)的算法,求树中第k小的结点的位置。
二叉排序树的类型BSTree定义如下:
typedef char KeyType;
typedef struct BSTNode {
KeyType key;
struct BSTNode *lchild,*rchild;
int lsize; // 新增域,值为左子树的结点数+1
} BSTNode, *BSTree;
实现下列函数:
BSTNode Ranking(BSTree T, int k);
/ 在含lsize域的二叉排序树T中,/
/ 求指向T中第k小的结点的指针 */
#include "allinclude.h" //DO NOT edit this line
BSTNode *Ranking(BSTree T, int k){
// Add your code here
if(!T) return NULL;
if(T->lsize == k) return T;
if(T->lsize > k) return Ranking(T->lchild,k);
else return Ranking(T->rchild,k-T->lsize);
}
十八、 假设二叉排序树T的每个结点的平衡因子域bf当前均为0。试编写算法,求二叉排序树T的深度,并为每个结点的bf域赋予正确的平衡因子值
【题目】假设二叉排序树T的每个结点的平衡因子域bf当前均为0。试编写算法,求二叉排序树T的深度,并为每个结点的bf域赋予正确的平衡因子值。
平衡二叉排序树的类型BBSTree定义如下:
typedef char KeyType;
typedef struct BBSTNode {
KeyType key;
int bf; // 平衡因子
struct BBSTNode *lchild,*rchild;
} BBSTNode, *BBSTree;
实现下列函数:
int Depth_BF(BBSTree T);
/* 求二叉排序树T的深度,并为每个结点 /
/ 的bf域赋予正确的平衡因子值。 */
#include "allinclude.h" //DO NOT edit this line
int Depth_BF(BBSTree T){
// Add your code here
int lf,rf;
if(!T) return 0;
else{
lf = Depth_BF(T->lchild);
rf = Depth_BF(T->rchild);
T->bf = lf-rf;
return 1+(lf>rf?lf:rf);
}
}
十九、编写平衡二叉排序树的右平衡处理算法
【题目】编写平衡二叉排序树的右平衡处理算法。
平衡二叉排序树的类型BBSTree定义如下:
typedef char KeyType;
typedef struct BBSTNode {
KeyType key;
int bf; // 平衡因子
struct BBSTNode *lchild,*rchild;
} BBSTNode, *BBSTree;
可调用下列旋转调整操作:
void L_Rotate(BBSTree &p); // 对最小失衡子树p做左旋调整
void R_Rotate(BBSTree &p); // 对最小失衡子树p做右旋调整
实现下列函数:
void RightBalance(BBSTree &T);
/* 实现对二叉树T的右平衡处理 */
#include "allinclude.h" //DO NOT edit this line
void RightBalance(BBSTree &T){
// Add your code here
BBSTree lc,rd;
rd = T->rchild;
switch(rd->bf){
case -1:
rd->bf = T->bf = 0;
L_Rotate(T);
break;
case 1:
lc = rd->lchild;
switch(rd->bf){
case -1:T->bf = 1;rd->bf = 0;break;
case 0:T->bf = rd->bf = 0;break;
case 1:T->bf = 0;rd->bf = -1;break;
}
lc->bf = 0;
R_Rotate(T->rchild);
L_Rotate(T);
break;
}
}