王道书 P150 T13(可以参考着P134 T5)

/**
 * 用二叉树链式存储实现 王道 P150 T13(求最近公共祖先)
 *
 * ①算法思想
 * 非递归后序遍历中,遍历到m时,栈内的元素就是m自己和m的所有祖先的指针;
 * 遍历到n时,栈内的元素就是n自己和n的所有祖先的指针。
 * 把m和n的所有祖先从栈中自下而上分别拷贝到各自的数组栈中,然后找到两个数组中最靠后重复的元素,就是m和n的最近公共祖先。
 * m和n的祖先数组个数可能不同也可能相同,但是会有一段元素是相同的,这就是两节点的公共祖先部分,
 * 当m和n的数组栈长度不同时,
 * 可以采用跑步思想(类似于链表中找公共节点),让个数较多的数组先出栈,直到两个数组长度相同,再一起跑,然后进行比较数组元素是否相等。
 * 当m和n等长时,
 * 就直接从后往前比较是否相等即可。
 * 
 * 注:可以参考着王道书 P134 T5
 * 
 *
 * ②算法设计
 */


#include <stdio.h>
#include <iostream>
#define MaxSize 100

typedef struct BiTreeNode{
    int data;
    BiTreeNode *lchild,*rchild;
}BiTreeNode,*BiTree;



//P150 T13
BiTree Ancestor(BiTree T,BiTree m,BiTree n){//m、n是两个节点的指针
    BiTree stack[MaxSize],p = T,mPre[MaxSize],nPre[MaxSize];//mPre和nPre两个数组用来保存m和n的祖先
    int top = -1,tag[MaxSize] = {0};
    int mtop = 0,ntop = 0;//mtop和ntop用来存一下mPre和nPre数组的长度,方便进行长度的比较
    while(p || top != -1){
        if(p){
            stack[++top] = p;
            tag[top] = 1;
            p = p -> lchild;
        }else{
            if(tag[top] == 1){
                tag[top] = 2;
                p = stack[top];
                p = p -> rchild;
            }else{//说明是叶子节点了
                p = stack[top--];
//                Visit(p);
                if(p == m){//此时栈内的元素就是m的所有祖先的指针
                    for (int i = 0; i <= top ; ++i) {
                        mPre[i] = stack[i];//把m的所有祖先都拷贝到mPre[]中
                    }
                    mtop = top;
                }
                if(p == n){//此时栈内的元素就是n的所有祖先的指针
                    for (int i = 0; i <= top ; ++i) {
                        nPre[i] = stack[i];//把n的所有祖先都拷贝到nPre[]中
                    }
                    ntop = top;
                }
                p = NULL;
            }
        }
    }
    while(mtop != ntop){
        if(mtop > ntop)
            mtop--;
        else
            ntop--;
    }
    //下面这个while可以直接这么写:
    //while(mPre[top--] -> data != nPre[top--] -> data)
    //注意这边使用while很方便,当while条件不满足时就说明找到了结果,然后直接return就可以了
    while(mPre[top] -> data != nPre[top] -> data){
        top--;
    }
    return mPre[top];//或者return nPre[top];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值