二叉树相关笔试题(三)

1.按之字形顺序打印二叉树


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

分析:可以用两个栈,在打印某层结点时,把下一层的子结点保存到相应的栈里。如果当前层是奇数层,则先保存左子节点再保存右子结点到第一个栈中,如果是偶数层,则先保存右子结点再保存左子节点到第二个栈中。
实现代码一:
    vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int> > result;
        stack<TreeNode *> stack1,stack2;
        if(pRoot!=NULL)
            stack1.push(pRoot);
        TreeNode *node = NULL;
        while(!stack1.empty() || !stack2.empty()){
            vector<int> data;
            if(!stack1.empty()){
                while(!stack1.empty()){
                    node = stack1.top();
                    stack1.pop();
                    data.push_back(node->val);
                    if(node->left!=NULL)
                        stack2.push(node->left);
                    if(node->right!=NULL)
                        stack2.push(node->right);
                }
                result.push_back(data);
            }
            else if(!stack2.empty()){
                while(!stack2.empty()){
                    node = stack2.top();
                    stack2.pop();
                    data.push_back(node->val);
                    if(node->right!=NULL)
                        stack1.push(node->right);
                    if(node->left!=NULL)
                        stack1.push(node->left);
                }
                result.push_back(data);
            }
        }
        return result;
    }

实现代码二:

    vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int> > result;      
        if(pRoot == NULL)
            return result;
          
        bool flag = true;
          
        queue<TreeNode *> q;        
        q.push(pRoot);         
        while(!q.empty())
        {
            int size = q.size();
            vector<int> num;
            while(size --)
            {
                TreeNode *cur = q.front();
                q.pop();
                num.push_back(cur->val);
                if(cur->left != NULL)
                {
                    q.push(cur->left);
                } 
                if(cur->right != NULL)
                {
                    q.push(cur->right);
                } 
            }
            if(!flag) 
            {
                reverse(num.begin(), num.end());
            }
            result.push_back(num);
            flag = !flag;
        }
        return result;
    }


2..把二叉树打印成多行

题目:从上到下打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印一行

分析:与层序遍历二叉树相似。

实现代码:

        vector<vector<int> > Print(TreeNode* pRoot) 
        {
            vector<vector<int> > vec;
             
            if(pRoot == NULL) 
                return vec;
  
            queue<TreeNode*> q;
            q.push(pRoot);
  
            while(!q.empty())
            {
                int lo = 0;
                int hi = q.size();
                vector<int> c;
                while(lo++ < hi)
                {
                    TreeNode *t = q.front();
                    q.pop();
                    c.push_back(t->val);
                    if(t->left) 
                    {
                        q.push(t->left);
                    }                      
                    if(t->right)
                    {
                        q.push(t->right);
                    }                        
                }
                vec.push_back(c);
            }
            return vec;
        }   

3.序列化二叉树

分析:按照先序遍历二叉树的顺序,先遍历根节点,再左结点,后右节点,当到“#”时,说明左结点或者右节点为NULL,同样反序列化也是一样的。

实现代码:

    char* Serialize(TreeNode *root) {    
        if(root==NULL)
            return NULL;
        string str;
        Serialize1(root,str);
        return const_cast<char*>(str.c_str());
    }
    TreeNode* Deserialize(char *str) {
        if(str==NULL||*str=='\0')
            return NULL;
        int num=0;
        return Deserialize1(str,num);
    }
    void Serialize1(TreeNode *root,string &str)
    {
        if(root==NULL)
        {
            str+="#,";
            return ;
        }
        char ch[10];
        sprintf(ch,"%d",root->val);
        str+=ch;
        str+=",";
        Serialize1(root->left,str);
        Serialize1(root->right,str);
    }
    TreeNode* Deserialize1(char *str,int &num)
    {
        int val=0;
        if(str[num]=='#')
        {
            num+=2;
            return NULL;
        }
        while(str[num]!=','&&str[num]!='\0')
        {
            val=val*10+str[num]-'0';
            num++;
        }
        num++;
        TreeNode *root=new TreeNode(val);
        root->left=Deserialize1(str,num);
        root->right=Deserialize1(str,num);
        return root;
    }

4.二叉搜索树的第K个结点

题目:给定一棵二叉搜索树,请找出其中第K大的结点。

分析:中序遍历一颗二叉搜索树,遍历的序列是递增的,因此只要中序遍历后,就可以找到它的第K大结点。

实现代码:

    TreeNode* KthNode(TreeNode* pRoot, unsigned int& k)
    {
        if(pRoot == NULL || k == 0)
        {
            return NULL;
        }
        TreeNode* ret = NULL;
        if(pRoot->left != NULL)
        {
            ret = KthNode(pRoot->left, k);    
        }
        if(ret == NULL)
        {
            if(k == 1)
            {
                ret = pRoot;
            }
            else
            {
                k--;
            }
        }
        if(ret == NULL && pRoot->right != NULL)
        {
            ret = KthNode(pRoot->right, k);
        }
        return ret;
    }


5.求树中两个结点的最低公共祖先

1). 如果是二叉搜索树,因为二叉搜索树的左子树的结点都比父结点小,右子树的结点都比父结点大,因此只需要从树的根结点开始与两个输入的结点比较,如果当前结点的值比它们都大,则最低的公共父结点在当前结点的左子树中,接着遍历当前结点的左子结点。如果当前结点的值比它们都小,则最低的公共父结点在当前结点的右子树中,接着遍历当前结点的右子结点。直到找到第一个在两个输入结点的值之间的结点,则这个结点就是最低的公共祖先。

2).如果只是一颗普通的树且有指向父结点的指针,则这个问题就转化成了求两个链表的第一个公共结点。

3).如果只是一颗普通的树且没有指向父结点的指针

方法一(需要对同一个节点遍历多次):可以从根节点遍历这棵树,每遍历到一个结点时 ,就判断两个输入结点是不是在它的子树中,如果在,则分别遍历它的所有子结点 ,并判断输入结点是否在它们的子树中,直到找到一个结点自己包含输入结点而它的的子结点中没有,则该结点就是最低的公共祖先。

方法二(借助辅助空间):用两个链表分别保存从根节点到输入结点的路径,然后就问题就转化成了求两个链表的最后公共结点。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值