编程题——关于树

本文介绍了多个剑指欧肥儿的二叉树问题,包括平衡二叉树、二叉树的深度、下一个结点、镜像、对称性等。每个问题提供了解题思路和代码示例,帮助读者理解二叉树操作的关键点和优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

目录

 

平衡二叉树(剑指欧肥儿)

二叉树的深度(剑指欧肥儿)

二叉树的下一个结点(剑指欧肥儿)

二叉树的镜像(剑指欧肥儿)

对称的二叉树(剑指欧肥儿)

把二叉树打印成多行(剑指欧肥儿)

按之字形顺序打印二叉树(剑指欧肥儿)

序列化二叉树(剑指欧肥儿)

二叉搜索树的第k个结点

数据流中的中位数(剑指欧肥儿)

重建二叉树(剑指欧肥儿)


  • 平衡二叉树(剑指欧肥儿)

题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。

解题代码一:

class Solution {
public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
        //排除特殊情况
        if(pRoot == NULL) return true;
        
        int leftTreeDep = getDepth(pRoot -> left);
        int rightTreeDep = getDepth(pRoot -> right);
        
        if(leftTreeDep - rightTreeDep > 1 || rightTreeDep - leftTreeDep > 1){
            return false;
        }
        return IsBalanced_Solution(pRoot -> left) && IsBalanced_Solution(pRoot -> right);
    }
    
    int getDepth(TreeNode* pRoot){
        //排除特殊情况
        if(pRoot == NULL) return 0;
        
        //递归算高度
        int leftDepth = getDepth(pRoot -> left);
        int rightDepth = getDepth(pRoot -> right);
        
        return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
        //return max(leftDepth + 1,rightDepth + 1); 这句和上面一句的return完全等效

    }
};

解题关键:

  1. 平衡二叉树的特点,它可以是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且它的左右两个子树都是一颗平衡二叉树。
  2. 单独写出一个计算树的高度的函数getDepth()
  3. 运用了两个递归,一个计算树的高度,一个判断每个子树是否满足平衡二叉树的特征。

解题代码二:

class Solution {
public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
        //排除特殊情况
        return getDepth(pRoot) != -1;
        
    }
    
    int getDepth(TreeNode* pRoot){
        //排除特殊情况
        if(pRoot == NULL) return 0;
        
        //递归算高度
        int leftDepth = getDepth(pRoot -> left);
        if(leftDepth == -1) return -1;
        int rightDepth = getDepth(pRoot -> right);
        if(rightDepth == -1) return -1;
        return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth);
    }
};

解题关键:

  1. 代码一是对树从上到下,对每层的左右节点进行计算树高度,每一次计算高度,都会重复计算下面的节点的高度,其实是没必要的。
  2. 代码二是对树从下到上(递归是从下开始递归的),计算每一个节点的高度,但没有重复计算任何一个节点的高度。
  3. 代码二是对代码一的改进,避免的不必要的计算,但思考量和难度更大。

题外话:

  1. C++中取绝对值的函数,int abs(int x),在这里不用引入库,可能牛客这个剑指的编译器引入了cmath库。
  2. C++取两个数的最大值的函数是 int max(int x,int y)
  3. 上面两个函数都要在,include<cmath> 的前提下

  • 二叉树的深度(剑指欧肥儿)

题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

解题代码:

class Solution {
public:
    int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot == NULL) return 0;
        
        int left = TreeDepth(pRoot -> left);
        int right = TreeDepth(pRoot -> right);
        
        return max(left + 1,right + 1);
        //return left > right ? left + 1 : right + 1;
    }
};

解题思路:

  1. 这个代码其实是上一道题的代码一的第二个函数getDepth,而return max(left + 1, right + 1)和上一道题的代码一getDepth的return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;是一个道理,两者完全可以相互替换。
  2. 这里要说一次,树的深度,结点的层数是从根开始定义起,根为第一层,根的孩子是第二层,以此类推。树中结点的最大层次称为树的深度(Depth)。

题外话:

要被if的判断条件判断为false的语句有,if(NULL)    if(0)      if(false)


  • 二叉树的下一个结点(剑指欧肥儿)

题目描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

解题代码:

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        //排除不可能
        if(pNode == NULL) return NULL;
        
        //如果该节点有右子节点
        TreeLinkNode* p = NULL;
        if(pNode -> right != NULL){
            p = pNode -> right;
            while(p -> left != NULL){
                p = p -> left;
            }
        }
        //如果该节点没有右节点
        else if(pNode -> next != NULL){
            //该节点还是父亲节点的右节点
            TreeLinkNode* pp;
            p = pNode;
            pp = p -> next;
            while(p == pp -> right && pp != NULL){
                p = pp;
                pp = pp -> next;
            }
            p = pp;
        }
        return p; 
            
    } 
}; 

解题思路:

  1. 这道题思路比较难,看了 答案也会想很久。
  2. 对于一个节点,对它进行分了三个类。

a:该节点有右节点,则它的下一个节点是它的右子树的最左节点。

b:该节点没有右节点,该节点还是它父节点的右节点,则我们沿着该节点的父亲节点一路往上遍历,直到找到一个节点x,x是它父亲节点的左节点。如果这样的节点存在,则这个父亲节点就是我们要找的下一个节点。如果这样的节点不存在,则我们要找的下一个节点为空。

c:该节点没有右节点,且是它父节点的左节点,则它的父亲节点就是下一个节点。


  • 二叉树的镜像(剑指欧肥儿)

题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。

输入描述:

二叉树的镜像定义:源二叉树 
    	    8
    	   /  \
    	  6   10
    	 / \  / \
    	5  7 9 11
    	镜像二叉树
    	    8
    	   /  \
    	  10   6
    	 / \  / \
    	11 9 7  5

解题代码一:

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        
        TreeNode* temp = NULL;
        if(pRoot != NULL){
            temp = pRoot -> left;
            pRoot -> left = pRoot -> right;
            pRoot -> right = temp;
            if(pRoot -> left != NULL){
                Mirror(pRoot -> left);    
            }
            if(pRoot -> right != NULL){
                Mirror(pRoot -> right);    
            }
        }
    }
    
};

解题思路:

  1. 首先根据输入描述,我们得知是将二叉树的每个棵子树的左右值交换。
  2. 于是从上到下,依次遍历每一层的左右节点并交换。
  3. 用到了递归思想,每一个非NULL节点都要递归这个函数Mirror。

解题代码二:

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot == NULL) return;
        
        TreeNode* temp = NULL;
        
        temp = pRoot -> left;
        pRoot -> left = pRoot -> right;
        pRoot -> right = temp;
        
        Mirror(pRoot -> left);    
        Mirror(pRoot -> right);    
        
    }
};

解题思路:

  1. 思路和代码1一模一样
  2. 但是这个代码写法更简洁,更一目了然

  • 对称的二叉树(剑指欧肥儿)

题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

解题代码一:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
        if(pRoot == NULL) return true;
        
       //首先生成左子树的镜像二叉树
        TreeNode* leftRoot = pRoot -> left;
        TreeNode* rightRoot = pRoot -> right;
        Mirror(leftRoot);
        
        //用镜像二叉树和右子树对比
        return IsEqual(leftRoot, rightRoot);
        
    }
    
    void Mirror(TreeNode* pRoot){
        if(pRoot == NULL) return;
        
        TreeNode* temp;
        temp = pRoot -> left;
        pRoot -> left = pRoot -> right;
        pRoot -> right = temp;
        
        Mirror(pRoot -> left);
        Mirror(pRoot -> right);
        
    }
    
    bool IsEqual(TreeNode* p1, TreeNode* p2){
        if(p1 == NULL && p2 == NULL) return true;
        
        if(p1 == NULL && p2 != NULL) return false;
        if(p2 == NULL && p1 != NULL) return false;
        
        if(p1 -> val == p2 -> val){
            return IsEqual(p1 -> left, p2 ->left) && IsEqual(p1 -> right, p2 -> right);
        }else{
            return false;
        }
    }
};

解题思路:

  1. 首先排除特殊情况,二叉树为空。
  2. 利用二叉树根节点的左子树生成镜像树,然后与二叉树的根节点的右子树作对比。
  3. 两个递归代码,一个生成镜像树,一个判断两个二叉树是否相等。

解题代码二:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
        return isSymmetrical(pRoot, pRoot);
    }
    bool isSymmetrical(TreeNode* p1, TreeNode* p2){
        if(p1 == NULL && p1 == NULL) return true;
        if(!p1 || !p2) return false;
        if(p1 -> val == p2 -> val){
            return isSymmetrical(p1 -> left,p2 -> right) && isSymmetrical(p1 -> right,p2 -> left);
        }else{
            return false;
        }
    }
};

解题思路:

  1. 和代码一的思路完全不一样,这个代码是一步到位的。
  2. 运用了重载的思想(相同函数名和返回值,不同参数个数)。
  3. 直接把给定的树,当做两棵相同的树,然后从上到下,从左往右得遍历比较两个数组。这个算法可以记下来,比较经典。

  • 把二叉树打印成多行(剑指欧肥儿)

题目描述:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

解题代码:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
        vector<vector<int> > Print(TreeNode* pRoot) {
            vector<vector<int>> res;
            if(pRoot == NULL) return res;
            queue<TreeNode*> q;
            q.push(pRoot);
            while(!q.empty()){
                int size = q.size();
                vector<int> temp;
                while(size--){
                    TreeNode* t;
                    t = q.front();
                    q.pop();
                    temp.push_back(t -> val);
                    
                    if(t -> left) q.push(t -> left);
                    if(t -> right) q.push(t -> right);
                }
                res.push_back(temp);
            }
            return res;
        }
};

解题思路:

  1. 循环里套循环,将树的每层节点值从左到右依次压入队列.
  2. 这个方法要记下来了,构思相当巧妙了。

队列:

  1. 第一次使用队列,记住几个方法,和stack很像。
  2. 得出队列最前面的值(先进先出)q.front();
  3. 弹出队列最前面的值 q.pop();
  4. 得出队列的长度 q.size();
  5. 把元素压入队列 q.push(t);

  • 按之字形顺序打印二叉树(剑指欧肥儿)

题目描述:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

解题代码:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int>> res;
        
        if(!pRoot) return res;
        
        stack<TreeNode*> s1;
        stack<TreeNode*> s2;
        int flag = 0;
        s1.push(pRoot);
        
        while(!s1.empty() || !s2.empty()){
            vector<int> temp;
            TreeNode* t;
            if(flag == 0){
                int size = s1.size();
                while(size--){
                    t = s1.top();
                    s1.pop();
                    temp.push_back(t->val);
                    if(t -> left) s2.push(t -> left);
                    if(t -> right) s2.push(t -> right);
                }
                res.push_back(temp);
                flag = 1;
            }else{
                int size = s2.size();
                while(size--){
                    t = s2.top();
                    s2.pop();
                    temp.push_back(t -> val);
                    if(t -> right) s1.push(t -> right);
                    if(t -> left) s1.push(t -> left);
                }
                res.push_back(temp);
                flag = 0;
            }
        }
        return res;
    }
    
};

解题思路:

  1. 这道题和上一道题“把二叉树打印成多行(剑指欧肥儿)”的思路类似,不同的是这道题是树的奇偶层按相反顺序打印。
  2. 经过我自己画二叉树分析,这道题必须要用两个栈,奇行用栈s1装下一行的数字,欧行用栈s2装下一行的数字。
  3. 对于栈s1是先装节点的左子节点再装右子节点,对于栈2则是先装节点的右子节点再装左子节点。(这个规律由画二叉树分析而来的)。

  • 序列化二叉树(剑指欧肥儿)

题目描述:请实现两个函数,分别用来序列化和反序列化二叉树。

解题代码:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
	char* Serialize(TreeNode *root) {   
        if(!root) return "#";
        string r = to_string(root->val);
        r.push_back(',');
        char *left = Serialize(root->left);
        char *right = Serialize(root->right);
        char *ret = new char[strlen(left) + strlen(right) + r.size()];
        strcpy(ret, r.c_str());
        strcat(ret, left);
        strcat(ret, right);
        return ret;
    }

	TreeNode* decode(char *&str) {
        if(*str=='#'){
            str++;
            return NULL;
        }
        int num = 0;
        while(*str != ',')
            num = num*10 + (*(str++)-'0');
        str++;
        TreeNode *root = new TreeNode(num);
        root->left = decode(str);
        root->right = decode(str);
        return root;
    }

	TreeNode* Deserialize(char *str) {
		return decode(str);
	}
};

解题思路:

  1. 序列化,就是前序遍历二叉树将每个节点的值输出,举例,一颗二叉树以7为根结点,8和2分别为它的左右两个子节点,生成的序列为"7,8,##2,##",返回指向序列第一个字符的指针
  2. 反序列化,就是把序列化得到的字符串,改为二叉树,返回二叉树的根节点。
  3. 这道题涉及到指针的指针,以及指针的指针,难度极高了。

新知识点:

  1. string 是一个类型,有函数 to_string(int x),这个函数可以把x转为string类型
  2. string.push_back在string后添加字符。
  3. strlen(string)和string.size()都可以得出string的长度,不包括‘\0’的长度。
  4. 将字符串string转为char*类型,用 string.c_str(), string.c_str()一般用在strcpy函数中。
  5. strcpy(char* a,  char* b),将字符串b复制到a,a上相同位上的字符被b的替换,b中最后一个字符'\0'也会放到a里去。
  6. strcat(char* a, char*b)将字符串b加在字符串a后。而对于string类型的a和b,要把b加在a的后面,用a.push_back(b)。
  7. 函数返回值为 char* ,不是返回string,string是需要转为char*
  8. 函数形参为**p,说明指针是需要改变的,假如要取p的值需要用**p,取p的地址用*p。同理函数形参用*&p,也是说明指针是要改变的,假如要取p的值,则用*p,取p的地址用p。这一项正确性存疑。
  9. 对于char*型的字符串x取长度,用strlen(x),而对于string型的字符串x取长度,用x.size()或x.length();

  • 二叉搜索树的第k个结点

题目描述:给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。

解题代码:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    TreeNode* KthNode(TreeNode* pRoot, int k)
    { 
        //排除不可能
        if (k < 1 || pRoot == NULL) return NULL;
        count = 0;
        
        return KthNodeCore(pRoot, k);
           
    }
private:
    int count;
    TreeNode* KthNodeCore(TreeNode* pRoot, int k){
        if(pRoot == NULL) return NULL;
        
        TreeNode* leftnode = KthNodeCore(pRoot -> left, k);
        if(leftnode != NULL){
            return leftnode; //得到值后一层一层地向上返回
        }
        
        if(++count == k){
            return pRoot; //返回当前的pRoot值,也就是这颗子树的根
        }
        
        TreeNode* rightnode = KthNodeCore(pRoot -> right, k);
        if(rightnode != NULL){
            return rightnode;
        }
        return NULL;
    }
};

解题思路:

  1. 二叉搜索树,就是按照中序遍历即可得到排好序的树节点的值,这道题也就是是用中序遍历得到第k大的值。
  2. 这道题最关键的一点,就是中序遍历的递归,难啃难懂。
  3. 记住这个代码,应为又tm难又很经典。

  • 数据流中的中位数(剑指欧肥儿)

题目描述:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

解题代码:

class Solution {
public:
    void Insert(int num)
    {
        //max和min里的数的总个数,为偶则新数存min,为奇则新数存max
        if( ( (max.size()+min.size()) & 1 ) == 0){ //已存在的数的个数是偶数
            if((max.size() > 0) && num < max[0]){ //如果num比max堆里最大的值小,则把num压入max,max的最大值压入min
                max.push_back(num);
                push_heap(max.begin(), max.end(), less<int>());
                num = max[0];
                pop_heap(max.begin(), max.end(), less<int>());
                max.pop_back();
            } 
            min.push_back(num);
            push_heap(min.begin(), min.end(), greater<int>());
        }else{//已存在的数的个数是奇数
            if(( min.size() > 0) && (num > min[0])){
                min.push_back(num);
                push_heap(min.begin(), min.end(), greater<int>());
                num  = min[0];
                pop_heap(min.begin(), min.end(), greater<int>());
                min.pop_back();
            }
            max.push_back(num);
            push_heap(max.begin(), max.end(), less<int>());
        }
    }

    double GetMedian()
    { 
        if((min.size() + max.size())%2){//大堆小堆总个数为奇数
            return min[0];
        }else{//大堆小堆总个数为偶数
            return double((min[0] + max[0]))/double(2);
        }
    }
    
private:
    vector<int> max;
    vector<int> min;

};

解题思路:

  1. 用到大小堆并且保持两堆的节点个数平衡。
  2. 首先要保证数据平均分配到两个堆里,因此两个堆中数据的数目之差不能超过1。为了实现平均分配,可以在数据的总数目是偶数时把新数据插入最小堆,否则插入最大堆。(用到奇偶数来判断)
  3. 其次要保证最大堆的所有数据都要小于最小堆中的数据。数据的总数是偶数时,按照前面的分配规则会把新数据插入最小堆,如果此时这个新数据比最大堆的最大值还要小,则把这个数字插入最大堆,然后把最大堆的最大数插入最小堆。由于最终插入最小堆的数字是原最大堆的最大数字,这样就保证了最小堆中所有数字都大于最大堆中的数字。
  4. 同理,当数据总数是奇数时,新数据也要和min的最小值比较,然后进行相同操作。

新知识点:

  1. 堆,是一种完全二叉树。一般默认为大堆。
  2. 大堆是每个父节点必然大于它的子节点的树,根节点是整棵树最大的值。小堆是每个父节点必然小于它的子节点的树,根节点是整棵树最小的值。
  3. 将vector类型的v数组整理为一个大堆树的序列:push_heap(v.begin(), v.end(). less<int>());整理成小堆的序列:push_heap(v.begin(), v.end(). greater<int>())。
  4. 整理为大堆的vector类型的v数组最大节点的值为v[0];整理为小堆的vector类型的v数组最小节点的值为v[0]
  5. 将堆的最大值(根节点)放数组的最后:pop_heap(v.begin(), v.end(). less<int>());同理,将堆的最小值(根节点)放数组的最后pop_heap(v.begin(), v.end(). greater<int>());
  6. 将vector数组v的最后一个元素弹出:pop_back();

  • 重建二叉树(剑指欧肥儿)

题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题代码:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        //递归首先排除NULL
        if(pre.empty()) return NULL;
        
        int size = pre.size();
        int gen = 0;
        vector<int> left_pre, left_in, right_pre, right_in;
        
        //根结点
        TreeNode* head = new TreeNode(pre[0]);
        
        //取到中序遍历的根结点
        for(int i = 0; i < size; i++){
            if(vin[i] == pre[0]){
                gen = i;
                break;
            }
        }
        
        //取gen左边的树
        for(int i = 0; i < gen; i++){
            left_in.push_back(vin[i]);
            left_pre.push_back(pre[i+1]);
        }
        
        //取gen右边的树
        for(int i = gen + 1; i < size; i++){
            right_in.push_back(vin[i]);
            right_pre.push_back(pre[i]);
        }        
        
        head -> left =  reConstructBinaryTree(left_pre, left_in);
        head -> right = reConstructBinaryTree(right_pre, right_in);
        
        return head;
    }
};

解题思路:

  1. 首先要明白如何根据前序遍历和中序遍历得到二叉树。
  2. 然后递归每一个节点。递归要注意一定不能漏掉递归的结束条件。
  3. 就算知道怎么重构二叉树的思路,也不定写得出来,所以要把这个代码背下来,如果考到直接拿来用。

由前序和中序得到二叉树的思路:

  1. 根据前序序列的第一个元素建立根结点;
  2. 在中序序列中找到该元素,确定根结点的左右子树的中序序列;
  3. 在前序序列中确定左右子树的前序序列;
  4. 由左子树的前序序列和中序序列建立左子树;
  5. 由右子树的前序序列和中序序列建立右子树。

如:已知一棵二叉树的先序遍历序列和中序遍历序列分别是abdgcefh、dgbaechf,求二叉树及后序遍历序列。 
先序:abdgcefh—>a bdg cefh
中序:dgbaechf—->dgb a echf

得出结论:a是树根,a有左子树和右子树,左子树有bdg结点,右子树有cefh结点。 
先序:bdg—>b dg

中序:dgb —>dg b

得出结论:b是左子树的根结点,b无右子树,有左子树。 
先序:dg—->d g

中序:dg—–>dg

得出结论:d是b左子树的根节点,d无左子树,g是d的右子树

然后对于a 的右子树类似可以推出

最后还原: a

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值