广工anyview数据结构第6章

第六章

PE06
/**********
【题目】若两棵二叉树T1和T2皆为空,或者皆不空
且T1的左、右子树和T2的左、右子树分别相似,则
称二叉树T1和T2相似。试编写算法,判别给定两棵
二叉树是否相似。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/

Status Similar(BiTree T1, BiTree T2)
/* 判断两棵二叉树是否相似的递归算法 */
{
    if(T1==NULL&&T2==NULL)
        return TRUE;
    else if(T1==NULL||T2==NULL)
        return FALSE;    
    if(Similar(T1->lchild,T2->lchild)&&Similar(T1->rchild,T2->rchild))
        return TRUE;
    else return FALSE;
}

PE17
/**********
【题目】编写递归算法,求对二叉树T先序遍历时
第k个访问的结点的值。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/

TElemType PreOrder(BiTree T, int &rek){
    TElemType re = '#';  
    if(T == NULL)
        return '#';
    if(rek == 1)
          return T -> data;    
    rek--;
    if(T -> lchild)
        re = PreOrder(T -> lchild, rek);    
    if(T -> rchild && re == '#')
        re = PreOrder(T -> rchild, rek);
    return re;  
}

TElemType PreOrderK(BiTree T, int k)
/* 求对二叉树T先序遍历时第k个访问的结点的值。*/
/* 若失败,则返回'#'                         */
{ 
     return PreOrder(T , k);
}

/*
int countNodes(BiTree bt){   
    return bt?(1 + countNodes(bt->lchild)+countNodes(bt->rchild)):0;
}
TElemType PreOrderK(BiTree T, int k) 
{
    int count;     
    if(k <= 0 || !T) return '#';
    if(k==1) return T->data;
    count = countNodes(T->lchild);
    return count >= --k ? PreOrderK(T->lchild,k) : PreOrderK(T->rchild,k-count);
}
*/

PE12
/**********
【题目】编写递归算法,计算二叉树T中叶子结点的数目。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/

int Leaves(BiTree T)
/* 计算二叉树T中叶子结点的数目 */
{
    if(T==NULL)
        return 0;
    if(T->lchild==NULL&&T->rchild==NULL)
        return 1;
    return Leaves(T->lchild)+Leaves(T->rchild);
}

PE21
/**********
【题目】试利用栈及其基本操作写出二叉树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 */
{
    Stack S;
    InitStack(S);
    BiTree p=T;
    while(p){
        visit(p->data);
        if(p->rchild)
            Push(S,p->rchild);
        if(p->lchild)
            p=p->lchild;
        else if(StackEmpty(S)!=TRUE)
            Pop(S,p);
        else p=NULL;                
    }
}

PE23
/**********
【题目】试利用栈及其基本操作写出二叉树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 */
{
    if(T == NULL) return;
    Stack s;   InitStack(s);    
    int fistIn=0,left=1,right=2;
    SElemType  now;
    now.ptr=T;
    now.tag=fistIn;
    Push(s,now);
    while(!StackEmpty(s)){
        Pop(s,now);
        if(now.tag==fistIn){    //如果当前是第一次进栈,先置为从左栈返回.
            now.tag=left;
            Push(s,now);            
            if(now.ptr->lchild){
                now.ptr=now.ptr->lchild;
                now.tag=fistIn;
                Push(s,now);
            }        
        }else if(now.tag==left){    //如果当前是从左栈返回的,先置为从右栈返回.
             now.tag=right;
             Push(s,now);             
             if(now.ptr->rchild){
                now.ptr=now.ptr->rchild;
                now.tag=fistIn;
                Push(s,now);
             }             
        }else{  //如果当前是从右栈返回的,则打印当前节点
             visit(now.ptr->data);        
        }    
    }
}

PE27
/**********
【题目】二叉树采用三叉链表的存储结构,试编写
不借助栈的非递归中序遍历算法。
三叉链表类型定义:
typedef struct TriTNode {
TElemType data;
struct TriTNode *parent, *lchild, *rchild;
} TriTNode, *TriTree;
**********/

void InOrder(TriTree PT, void (*visit)(TElemType))
/* 不使用栈,非递归中序遍历二叉树PT,  */
/* 对每个结点的元素域data调用函数visit */
{
    TriTree p=PT;
    while(p->lchild)
        p=p->lchild;    //找到最左子树
    while(p){
        visit(p->data); 
        if(p->rchild){  //p有右子树
            p=p->rchild;    //右子树的输出顺序是从根到叶
            while(p->lchild)    //如果右子树存在左子树
                p=p->lchild;    //找到右子树的最左子树并输出
        }
        else if(p->parent->lchild==p)   //p是左子树
            p=p->parent;    //输出双亲节点
        else{   //p是右子树并且没有右子树了,说明p的双亲节点已经输出了
            p=p->parent;    //判断一个右子树的双亲的双亲
            while(p->parent&&p->parent->rchild==p)  //p是右子树并且还有双亲时
                p=p->parent;    //右子树的双亲都已经被输出了
            p=p->parent;    //如果是左子树,输出双亲结点
        }   //如果是没有双亲在循环结束后函数结束
    }    
}

PE29
/**********
【题目】假设在三叉链表的结点中增设一个标志域
(mark取值0,1或2)以区分在遍历过程中到达该结点
时应继续向左或向右或访问该结点。试以此存储结
构编写不用栈辅助的二叉树非递归后序遍历算法。
带标志域的三叉链表类型定义:
typedef struct TriTNode {
TElemType data;
struct TriTNode *lchild, *rchild, *parent;
int mark; // 标志域
} TriTNode, *TriTree;
**********/

void PostOrder(TriTree T, void (*visit)(TElemType))
/* 不使用栈,非递归后序遍历二叉树T,   */
/* 对每个结点的元素域data调用函数visit */
{
    TriTree p;
    p=T;
    while(p){
        while(p->mark==0){  //先从叶遍历左孩子
            p->mark=1;
            if(p->lchild)
                p=p->lchild;
        }
        while(p->mark==1){  //再从叶遍历右孩子
            p->mark=2;
            if(p->rchild)
            p=p->rchild;
        }
        if(p->mark==2){ //夫节点一定为mark==1
            visit(p->data);
            p=p->parent;
        }
    }
}

PE33
/**********
【题目】编写递归算法,将二叉树中所有结点的
左、右子树相互交换。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/

void ExchangeSubTree(BiTree &T)
/* 将二叉树中所有结点的左、右子树相互交换 */
{
    BiTree p;
    if(T->lchild||T->rchild){
        p=T->lchild;
        T->lchild=T->rchild;
        T->rchild=p;
    }
    if(T->lchild)
        ExchangeSubTree(T->lchild);
    if(T->rchild)
        ExchangeSubTree(T->rchild);
}

PE37
/**********
【题目】编写递归算法:求二叉树中以元素值
为x的结点为根的子树的深度。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/

int Depthx(BiTree T, TElemType x)
/* 求二叉树中以值为x的结点为根的子树深度 */
{
    int depthLeft,depthRight;
    if(!T)
        return 0;
    if(T->data==x){
        depthLeft = Depthx(T->lchild,T->lchild->data);
        depthRight = Depthx(T->rchild,T->rchild->data);
        return 1+(depthLeft>depthRight?depthLeft:depthRight);
    }
    else{
        depthLeft = Depthx(T->lchild,x);
        depthRight = Depthx(T->rchild,x);
        return depthLeft>depthRight?depthLeft:depthRight;
    }
}

/**********
【题目】编写递归算法:对于二叉树中每一个元素值为x
的结点,删去以它为根的子树,并释放相应的空间。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/

void ReleaseX(BiTree &T, char x)
/* 对于二叉树T中每一个元素值为x的结点, */
/* 删去以它为根的子树,并释放相应的空间 */
{
    if(!T)  return ;
    if(T->data==x){
        ReleaseX(T->lchild,T->lchild->data);
        ReleaseX(T->rchild,T->rchild->data);
        free(T);
    }    
    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 */
{
    if(!T){
        TT=NULL;
        return ;        
    }
    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是否为完全二叉树 */
{
    if(T==NULL)
        return TRUE;
    int F = 0;
    BiTree p =  T;
    Queue Q;
    InitQueue(Q);
    EnQueue(Q,p);
    while(DeQueue(Q,p)){
    //将所有位置都入队,任一个位置为空后,后面再有就是非完全二叉树
        if(p==NULL)
            F=1;
        else if(F)
            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  */
{
    if(!T||(!T->lchild&&!T->rchild))
        return TRUE;
    if(T->lchild->data.key>=T->data.key)
        return FALSE;
    if(T->rchild->data.key<=T->data.key)
        return FALSE;
    if(IsBSTree(T->lchild))
        return IsBSTree(T->rchild);
    return FALSE;
} 

/**********
【题目】编写递归算法,从大到小输出给定二叉排序树
中所有关键字不小于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)输出  */
{
    if(!T)
        return ;
    OrderOut(T->rchild,k,visit);
    if(T->data.key>=k){
        visit(T->data);
        OrderOut(T->lchild,k,visit);
    }
}

/**********
【题目】试写一非递归算法,在二叉查找树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的非递归算法 */
{  
    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;
        }        
        if(p->data.key<k.key){
            if(p->rchild)
                p = p->rchild;
            else
                p->rchild = s;
        }     
    }    
}

/**********
【题目】试编写算法,求二叉树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);
**********/

Status getPathStack(Stack &s,BiTree t,TElemType v)
{
    if(t == NULL) return ERROR;
    SElemType e;
    e.ptr = t;
    if (t->data == v) {
        Push(s,e);
        return OK;
    }
    if (OK == getPathStack(s,t->lchild,v)) {
        Push(s,e);
        return OK;
    }
    if (OK == getPathStack(s,t->rchild,v)) {
        Push(s,e);
        return OK;
    }
    Pop(s,e);
    return ERROR;
}    
 
BiTree CommAncestor(BiTree T, TElemType a, TElemType b)
/* 求二叉树T中结点a和b的最近共同祖先 */
{
    if (T == NULL) return NULL;
    Stack sa,sb;    
    InitStack(sa);
    InitStack(sb);
    if (ERROR == getPathStack(sa,T,a)) return NULL;
    if (ERROR == getPathStack(sb,T,b)) return NULL;
    SElemType E1,E2,e1,e2;
    Pop(sa,E1);
    Pop(sb,E2);
    while (!StackEmpty(sa) && !StackEmpty(sb)) {
        e1 = E1;
        e2 = E2; 
        if (ERROR == Pop(sa,E1) || ERROR == Pop(sb,E2) || E1.ptr->data != E2.ptr->data || E1.ptr->data == a || E2.ptr->data == b)
            return e1.ptr;
    }
    return NULL;
}

/**********
【题目】在二叉排序树的每个结点中增设一个lsize域,
其值为该结点的左子树中的结点数加1。试编写时间复杂
度为O(logn)的算法,求树中第k小的结点的位置。
二叉排序树的类型BSTree定义如下:
typedef char KeyType;

typedef struct BSTNode {
KeyType key;
struct BSTNode *lchild,*rchild;
int lsize; // 新增域,值为左子树的结点数+1
} BSTNode, *BSTree;
**********/

{
    if(!T)
        return NULL;
    if(T->lsize==k)
        return T;
    else if(T->lsize > k)
        return Ranking(T->lchild,k);   //最小在左子树的最左孩子
    else
        return Ranking(T->rchild,k-T->lsize);  //最大在右子树的最右孩子
        //右子树比根结点和其左子树都要大,所以要减去
}

/**********
【题目】假设二叉排序树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域赋予正确的平衡因子值。      */
{
    int lf,rf;
    if(!T)
        return 0;
    lf = Depth_BF(T->lchild);
    rf = Depth_BF(T->rchild);
    T->bf = lf-rf;
    return 1+(lf>rf?lf:rf);
}

发布了12 篇原创文章 · 获赞 2 · 访问量 229

猜你喜欢

转载自blog.csdn.net/m0_46140702/article/details/103828595