二叉树的先中后非递归遍历,以及树的高度和叶子节点求解等面试题

利用栈容器可以实现二叉树的非递归遍历

首先将每个节点都设置一个标志,默认标志为假,根据节点的的状态进行如下流程。
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"seqstack.h"

//树的节点类型
typedef struct  node
{
	int flag;
	//数据域
	char ch;
	//指针域
	struct  node *lchild;
	struct  node *rchild;

}NODE;
int main()
{
	NODE nodeA = { 0,'A',NULL,NULL };
	NODE nodeB = { 0,'B',NULL,NULL };
	NODE nodeC = { 0,'C',NULL,NULL };
	NODE nodeD = { 0,'D',NULL,NULL };
	NODE nodeE = { 0,'E',NULL,NULL };
	NODE nodeF = { 0,'F',NULL,NULL };
	NODE nodeG = {0, 'G',NULL,NULL };
	NODE nodeH = {0, 'H',NULL,NULL };

	//建立关系
	nodeA.lchild = &nodeB;
	nodeA.rchild = &nodeF;

	nodeB.rchild = &nodeC;

	nodeC.lchild = &nodeD;
	nodeC.rchild = &nodeE;

	nodeF.rchild = &nodeG;
	nodeG.lchild = &nodeH;

	//初始化栈 (手动实现的栈)
	SeqStack stack = Init_seqstack();
	Push_SeqStack(stack,&nodeA);
	while ( !IsEmpty_SeqStack(stack))
	{
		NODE *top = (NODE *)GetTop_SeqStack(stack);
		Pop_SeqStack(stack);
		if (top->flag == 1)
		{
			printf("%c ",top->ch);
			continue;
		}
		top->flag = 1;
		if(top->rchild != NULL)
			Push_SeqStack(stack,top->rchild);
		Push_SeqStack(stack,top);
		if (top->lchild != NULL)
			Push_SeqStack(stack,top->lchild);
	}
	system("pause");
	return 0;
}

将代码稍作修改应用于LeetCode中的前中后非递归遍历二叉树
94 144 145(题号)

执行结果:通过显示详情
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:8.1 MB, 在所有 C++ 提交中击败了90.71%的用户

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> v;
        example(root, v);
        return v;
    }
 
    void example(TreeNode *root, vector<int> &path){
        stack<pair<TreeNode *, bool>> s;
        s.push(make_pair(root, false));
        bool flag;
        while(!s.empty()) 
        {
            root = s.top().first;
            flag = s.top().second;
            s.pop();
            if(root == NULL)
                continue;
            if(flag)
                path.push_back(root->val);
            else 
            {
            		//调整插入顺序即先中后序遍历 比如这里是后序遍历 按照后序遍历的左右根反着插入即可 依次类推
                    s.push(make_pair(root, true));
                    s.push(make_pair(root->right, false));
                    s.push(make_pair(root->left, false));
            }
        }
    }
};

递归遍历,深度以及叶子节点数量求解

typedef struct _PTNode{
char ch;
struct _PTNode* lchild;
struct _PTNode* rchild;
}PTNode;
//递归遍历
void RecursionBiTree(PTNode* root){
if (root == NULL){
return; }
//printf("%c", root->ch); //先序遍历
RecursionBiTree(root->lchild);
printf("%c", root->ch); //中序遍历
RecursionBiTree(root->rchild);
//printf("%c", root->ch); //后序遍历
}
//求叶子结点数量
int leafNum = 0;
void RecursionBiTree(PTNode* root){
if (root == NULL){
return; }
if (!root->lchild && !root->rchild){
leafNum++;
}
RecursionLeafNumTree(root->lchild);
RecursionLeafNumTree(root->rchild);
}
//求二叉树深度
int RecursionTreeDepth(PTNode* root){
int depth = 0;
if (root == NULL){
return depth;
}
int ldepth = RecursionTreeDepth(root->lchild);
int rdepth = RecursionTreeDepth(root->rchild);
depth = ldepth >= rdepth ? ldepth + 1 : rdepth + 1;
return depth;
}

已知先序,中序遍历结果,重建二叉树 (剑指offer 面试题6)
先序的第一个元素是根节点,找到和这个根节点相同的中序的位置,这个位置左边是左子树,右边是右子树。重复以上步骤

class Solution 
{
    TreeNode buildTree(int[] preorder, int[] inorder)
    {
        return help(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }
    
    TreeNode help(int[] preorder,int l1,int r1,int[] inorder,int l2,int r2)
    {
        if(l1>r1||l2>r2) return null;//临界
        int i =l2;
        while(inorder[i]!=preorder[l1])//寻找根节点在中序的位置
        {
            i++;
        }
        TreeNode root = new TreeNode(preorder[l1]);
        root.left = help(preorder,l1+1,l1+i-l2,inorder,l2,i-1);
        root.right = help(preorder,l1+i-l2+1,r1,inorder,i+1,r2);
        return root;
    }

二叉树中和为某一值的路径

class Solution {
private:
    vector<int> path;
    vector<vector<int>> res;
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        dfs(root, sum);
        return res;
    }

    void dfs(TreeNode* curr, int target)
    {
        if (curr != nullptr)
        {
            target -= curr->val;
            path.push_back(curr->val);
            if (target != 0 || curr->left != nullptr || curr->right != nullptr)
            {
                dfs(curr->left, target);
                dfs(curr->right, target);
            }
            else
            {
                res.push_back(path);
            }
            path.pop_back();
        }
    }
};

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    Node *pre, *head;
    Node* treeToDoublyList(Node* root) 
    {
        if(root==NULL) 
        	return NULL;
        dfs(root);
        head->left=pre;
        pre->right=head;
        return head;
    }

    void dfs(Node* cur)
    {
        if(cur==NULL)
        	return;
        dfs(cur->left);
        
        if(pre!=NULL) 
        	pre->right=cur;
        else 
        	head=cur;
        	
        cur->left=pre;
        pre=cur; 
        
        dfs(cur->right);
    }
};
posted @ 2022-09-29 19:40  J1nu  阅读(22)  评论(0)    收藏  举报