C++二叉树遍历总结\100. Same Tree

转载请注明出处:http://blog.csdn.net/c602273091/article/details/55195284

理论学习

概念介绍

二叉树的遍历分成前序、中序、后序遍历。

前序就是访问结点的操作发生在遍历其左右子树之前。
中序就是访问结点的操作发生在遍历其左右子树之中,一般是遍历左边子树以后。
后序就是访问结点的操作发生在遍历其左右子树之后。

这里可以参考【1】中,对数据结构做了一个整理。

遍历图解

这里写图片描述
图中每个节点经过了3次。

先序为: A B D C E F
中序为: D B A E C F
后序为: D B E F C A

PS:(1) 在搜索路线中,若访问结点均是第一次经过结点时进行的,则是前序遍历;若访问结点均是在第二次(或第三次)经过结点时进行的,则是中序遍历(或后序遍历)。只要将搜索路线上所有在第一次、第二次和第三次经过的结点分别列表,即可分别得到该二叉树的前序序列、中序序列和后序序列。
  (2) 上述三种序列都是线性序列,有且仅有一个开始结点和一个终端结点,其余结点都有且仅有一个前趋结点和一个后继结点。为了区别于树形结构中前趋(即双亲)结点和后继(即孩子)结点的概念,对上述三种线性序列,要在某结点的前趋和后继之前冠以其遍历次序名称。上图所示的二叉树中结点C,其前序前趋结点是D,前序后继结点是E;中序前趋结点是E,中序后继结点是F;后序前趋结点是F,后序后继结点是A。但是就该树的逻辑结构而言,C的前趋结点是A,后继结点是E和F。

二叉树建立过程可以看:【2】

// 假设虚结点输入时以空格字符表示,相应的构造算法为:
void CreateBinTree (BinTree *T) { 
//构造二叉链表。T是指向根指针的指针,故修改*T就修改了实参(根指针)本身
    char ch;
    if((ch=getchar())=='') *T=NULL//读人空格,将相应指针置空 
    else{ //读人非空格
        *T=(BinTNode *)malloc(sizeof(BinTNode)); //生成结点
        (*T)->data=ch;
        CreateBinTree(&(*T)->lchild); //构造左子树
        CreateBinTree(&(*T)->rchild); //构造右子树
     }
}

遍历算法

1.中序遍历的递归算法定义:若二叉树非空,则依次执行如下操作:
(1)遍历左子树;
(2)访问根结点;
(3)遍历右子树。

2.先序遍历的递归算法定义:若二叉树非空,则依次执行如下操作:
(1) 访问根结点;
(2) 遍历左子树;
(3) 遍历右子树。

3.后序遍历得递归算法定义:若二叉树非空,则依次执行如下操作:
(1)遍历左子树;
(2)遍历右子树;
(3)访问根结点。

对于这个详细的图解,可以看【8】。

代码实践

参考【3】【4】中的代码建立二叉树。

实现模板

在【5】里,作者总结了一套很好的二叉树遍历的模板。以下为摘录部分。

前序遍历:

//前序遍历
void preorder(TreeNode *root, vector<int> &path)
{
    if(root != NULL)
    {
        path.push_back(root->val);
        preorder(root->left, path);
        preorder(root->right, path);
    }
}

中序遍历:

//中序遍历
void inorder(TreeNode *root, vector<int> &path)
{
    if(root != NULL)
    {
        inorder(root->left, path);
        path.push_back(root->val);
        inorder(root->right, path);
    }
}

后序遍历:

//后续遍历
void postorder(TreeNode *root, vector<int> &path)
{
    if(root != NULL)
    {
        postorder(root->left, path);
        postorder(root->right, path);
        path.push_back(root->val);
    }
}

非递归的前序:

//非递归前序遍历
void preorderTraversal(TreeNode *root, vector<int> &path)
{
    stack<TreeNode *> s;
    TreeNode *p = root;
    while(p != NULL || !s.empty())
    {
        while(p != NULL)
        {
            path.push_back(p->val);
            s.push(p);
            p = p->left;
        }
        if(!s.empty())
        {
            p = s.top();
            s.pop();
            p = p->right;
        }
    }
}

非递归的中序:

//非递归中序遍历
void inorderTraversal(TreeNode *root, vector<int> &path)
{
    stack<TreeNode *> s;
    TreeNode *p = root;
    while(p != NULL || !s.empty())
    {
        while(p != NULL)
        {
            s.push(p);
            p = p->left;
        }
        if(!s.empty())
        {
            p = s.top();
            path.push_back(p->val);
            s.pop();
            p = p->right;
        }
    }
}

非递归的后序:

//非递归后序遍历-迭代
void postorderTraversal(TreeNode *root, vector<int> &path)
{
    stack<TempNode *> s;
    TreeNode *p = root;
    TempNode *temp;
    while(p != NULL || !s.empty())
    {
        while(p != NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点
        {
            TreeNode *tempNode = new TreeNode;
            tempNode->btnode = p;
            tempNode->isFirst = true;
            s.push(tempNode);
            p = p->left;
        }
        if(!s.empty())
        {
            temp = s.top();
            s.pop();
            if(temp->isFirst == true)   //表示是第一次出现在栈顶
            {
                temp->isFirst = false;
                s.push(temp);
                p = temp->btnode->right;
            }
            else  //第二次出现在栈顶
            {
                path.push_back(temp->btnode->val);
                p = NULL;
            }
        }
    }
}

在【5】中,作者提出了更加简单的二叉树实现,推荐看看。

在【6】中,作者提出了二叉树先中后序遍历(递归&非递归)算法、层次遍历(正序&逆序&锯齿形)非递归算法、二叉树深度算法、结点总数算法。

还有一些应用,比如搜索:二叉树的查找【7】

bintree search_tree(bintree t,datatype x){  
    if(!t){  
        return NULL;  
    }  
    if(t->data == x){  
        return t;  
    }else{  
        if(!search_tree(t->lchild,x)){  
            return search_tree(t->rchild,x);  
        }  
        return t;  
    }  
}  

统计节点的个数:

int count_tree(bintree t){  
    if(t){  
        return (count_tree(t->lchild)+count_tree(t->rchild)+1);  
    }  
    return 0;  
}  

比较两个数是否相同:

int is_equal(bintree t1,bintree t2){  
    if(!t1 && !t2){      //都为空就相等  
        return 1;  
    }  
    if(t1 && t2 && t1->data == t2->data){      //有一个为空或数据不同就不判断了  
        if(is_equal(t1->lchild,t2->lchild))  
            if(is_equal(t1->rchild,t2->rchild)){  
                return 1;  
            }  
    }  
    return 0;  
}

100. Same Tree

题目描述

Given two binary trees, write a function to check if they are equal or not.

Two binary trees are considered equal if they are structurally identical and the nodes have the same value.

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSameTree(TreeNode* t1, TreeNode* t2) {
        if(!t1 && !t2){      //都为空就相等  
            return true;  
        }  
        if(t1 && t2 && t1->val == t2->val){      //有一个为空或数据不同就不判断了  
            if(isSameTree(t1->left,t2->left))  
                if(isSameTree(t1->right,t2->right)){  
                    return true;  
                }  
        }  
        return false;          
    }
};

【1】数据结构整理:http://student.zjzk.cn/course_ware/data_structure/web/shu/shu6.3.1.htm
【2】二叉树建立动画过程:http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/erchashujianli.htm
【3】建立二叉树:http://blog.csdn.net/pony_maggie/article/details/38390513
【4】二叉树的三种遍历方法:http://blog.csdn.net/presidentpresident/article/details/7549170
【5】二叉树各种方法总结:http://www.jianshu.com/p/49c8cfd07410
【6】二叉树各种遍历方法:http://www.cnblogs.com/yfsmooth/p/4671903.html
【7】二叉树的很多应用:http://blog.csdn.net/fansongy/article/details/6798278/
【8】二叉树详细图解:http://www.cnblogs.com/yc_sunniwell/archive/2010/06/27/1766233.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值