美文网首页
剑指offer 26 树的非递归遍历

剑指offer 26 树的非递归遍历

作者: 再凌 | 来源:发表于2020-05-01 12:33 被阅读0次

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。

解题思路

C语言的非递归方法. 可能是测试用例中没有深层次的二叉树(10000个节点的最大深度13), 因此内存使用优势没有展现出来. 深层次反复调用递归肯定是内存爆表的.

整体思路和树的非递归遍历方法一致, 将符合要求的节点存储起来(本方法使用了Tree链表结构保存节点信息),在下一次的循环中取出检查

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct Tree {
    struct TreeNode *pos;
    struct Tree *next;
};

//工具函数: 向某个Tree中添加节点
void addNode(struct Tree *head, struct TreeNode *item)
{
    struct Tree *temp = (struct Tree*)malloc(sizeof(struct Tree));
    temp->pos = item;
    temp->next = head->next;
    head->next = temp;
}

//工具函数: 在某个Tree中取得一个TreeNode节点, 并释放Tree中所占空间
//本函数不检查是否为空!
struct TreeNode* findNode(struct Tree *head)
{
    struct Tree *temp =head->next;
    head->next = temp->next;
    struct TreeNode *result = temp->pos;
    free(temp);
    return result;
}

 //工具函数: 在A中找到起始位置, 将所有符合的起始位置都加入startA
 //如果没有找到, 则返回false
bool findPosition(struct Tree *startA, struct TreeNode *A, int val)
{
    struct TreeNode *pos = A;
    struct Tree *mark = (struct Tree*)malloc(sizeof(struct Tree));//先序遍历
    mark->next = NULL;
    while(pos)
    {
        while(pos)
        {
            if(pos->val == val)
                addNode(startA, pos);
            if(pos->right) addNode(mark, pos->right);
            pos = pos->left;
        }
        if(mark->next) pos = findNode(mark);
    }

    if(startA->next) 
        return true;
    else
        return false;
}


bool isSubStructure(struct TreeNode* A, struct TreeNode* B){
    if(A == NULL) return false;
    if(B == NULL) return false;
    int result = 1;
    struct Tree *checkA = (struct Tree*)malloc(sizeof(struct Tree));//对于每一个有起始节点的位置, checkA链表保存非递归
    struct Tree *checkB = (struct Tree*)malloc(sizeof(struct Tree));//同上
    struct Tree *startA = (struct Tree*)malloc(sizeof(struct Tree));//保存每一个符合起始值符合要求的节点
    startA->next = NULL;


    if(!findPosition(startA,A, B->val))//没有找到起始节点
        return false;


    while(startA->next)//对于每一个符合要求的起始节点开始遍历
    {
        result = 1;
        checkA->next = startA->next;//因为这里直接是将一个Tree节点从startA转移到checkA中, 因此不能使用findNode()(会被释放!)
        startA->next = checkA->next->next;

        checkB->next = NULL;    //重新初始化checkB链表
        addNode(checkB, B);
    
        
        while(checkB->next)//一直检查到checkB为空, 如果中途有不符合, 会提前退出并置result = 0
        {
            struct TreeNode *tempB = findNode(checkB);
            struct TreeNode *tempA = findNode(checkA);

            bool Ahas = (tempA->left), Bhas = (tempB->left);
            if(!Ahas && Bhas) //如果A无子树, 但是B有子树, 那么不符合. 下同
            {
                result = 0;
                break;
            }
            Ahas = (tempA->right), Bhas = (tempB->right);
            if(!Ahas && Bhas)
            {
                result = 0;
                 break;
            }

            //对比AB的左右子树
            if((tempA->left) && (tempB->left))
            {
                if(tempA->left->val != tempB->left->val)
                {
                    result = 0;
                    break;
                }
                addNode(checkA, tempA->left);//将左右子树加入checkA/B链表,等待下一次循环时检查
                addNode(checkB, tempB->left);
            }

             //可选择的优化策略: 只加入右子树, 左子树直接通过tempA/B = tempA/B->left并continue循环检查


             
            if((tempA->right) && (tempB->right))
            {
                if(tempA->right->val != tempB ->right->val)
                {
                    result = 0;
                    break;
                }
                addNode(checkA, tempA->right);
                addNode(checkB, tempB->right);
            }
         }
         if(result) return true;//循环结束时因为result==1, 表明全都匹配
            
    }
    return false;
}

相关文章

  • 剑指offer 26 树的非递归遍历

    输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)B是A的子结构, 即 A中有出现和...

  • LeetCode | 面试题33. 二叉搜索树的后序遍历序列【剑

    LeetCode 面试题33. 二叉搜索树的后序遍历序列【剑指Offer】【Medium】【Python】【递归】...

  • 树的遍历算法

    树的递归遍历 树的层次遍历 树的非递归前序遍历 树的非递归中序遍历

  • 二叉树遍历java,非递归、层次。

    /** * 前序遍历 * 递归 */ /*** 前序遍历* 非递归*/ 后续遍历非递归 二叉树层次遍历基于java...

  • 二叉树遍历

    二叉树的遍历 1. 前序遍历 1.1 递归前序遍历 1.2 非递归前序遍历 2 中序遍历 2.1递归遍历 2.2非...

  • 剑指offer4J【C2 P6】倒序打印链表

    题目 倒序打印链表 题解 递归 非递归方式 我们使用栈即可 源码: 剑指offer4J[https://githu...

  • 总结

    1、二叉树广度遍历(非递归) 广度遍历非递归实现需要依靠一个队列。 2、二叉树深度遍历(递归与非递归,前序,中序和...

  • 二叉树遍历

    先序遍历——[递归、非递归] 中序遍历——[递归、非递归] 后序遍历——[递归、非递归] 层次遍历——[递归、非递归]

  • 二叉树,非递归法

    递归法 二叉树的递归,有前序遍历、中序遍历、后序遍历,一般采用递归法,比较简单 非递归法 二叉树非递归法,采用栈来实现

  • 二叉树的相关操作(一)

    上次写了二叉树遍历,其中在非递归的遍历中,只写了前序遍历,没有写非递归中序遍历和后续遍历。非递归要用到栈,只要根据...

网友评论

      本文标题:剑指offer 26 树的非递归遍历

      本文链接:https://www.haomeiwen.com/subject/hgafghtx.html