码迷,mamicode.com
首页 > 编程语言 > 详细

构造数组的MaxTree

时间:2016-04-01 14:23:44      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

【说明】:

  本文是左程云老师所著的《程序员面试代码指南》第一章中“构造数组的MaxTree”这一题目的C++复现。

  本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

  感谢左程云老师的支持。

【题目】:

  定义二叉树节点如下:

技术分享
class Node
{
public:
    Node(int data)
    {
        value = data;
        left = NULL;
        right = NULL;
    }
public:
    int value;
    Node *left;
    Node *right;
};
View Code

  一个数组的 MaxTree 定义如下:

  •   数组必须没有重复元素;
  •   MaxTree 是一棵二叉树,数组的每一个值对应一个二叉树节点;
  •   包括 MaxTree 树在内且在其中一的每一棵子树上,值最大的节点都是树的头。

  给定一个没有重复元素的数组 arr,写出生成这个数组的 MaxTree 的函数,要求如果数组长度为 N,则时间复杂度为 O(N),额外空间复杂度为 O(N)。

 【思路】:

  利用栈找到每个数左右两边第一个比它大的数,并且用hash_map保存。(估计这样说大家都不明白,大家可以看原书,或者分析代码喽)

【编译环境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

 【实现】:

  实现及测试代码:

技术分享
#include <sstream>

using namespace std;
using namespace __gnu_cxx;

class Node
{
public:
    Node(int data)
    {
        value = data;
        left = NULL;
        right = NULL;
    }
public:
    int value;
    Node *left;
    Node *right;
};

/*
 *函数说明:利用hash_map分别为每一个数的左边和右边第一个最大值(序号)设定关联
 *输入参数:s为存放数组序号的栈;map为待建好的映射表
 *输出参数:s为存放数组序号的栈;map为整理好的映射表
 *返回值:
 */
void popStackSetMap(stack<int> &s,hash_map<int,string> &map)
{
    int tmp = s.top();
    s.pop();
    stringstream ss;
    string str;
    if(s.empty())
    {
        map[tmp] = str;
    }
    else
    {
        ss << s.top();
        ss >> str;
        map[tmp] = str;        //序号对应序号的关系
    }
    return ;
}




Node* getMaxTree(int a[],int len)
{
    stack<int> s;
    hash_map<int,string> lBigMap;
    //为数组内的每个数据分别对应一个左端第一个最大值,没有则为空
    for(int i=0; i<len; i++)
    {
        while(!s.empty() && a[s.top()] < a[i])
            popStackSetMap(s,lBigMap);
        s.push(i);    //注意,这里保存的是数组序号,而不是数组值
    }
    while(!s.empty())
        popStackSetMap(s,lBigMap);
    //为数组内的每个数据分别对应一个右端第一个最大值,没有则为空
    hash_map<int,string> rBigMap;
    for(int i=len-1; i>=0; i--)
    {
        while(!s.empty() && a[s.top()] < a[i])
            popStackSetMap(s,rBigMap);
        s.push(i);    //注意,这里保存的是数组序号,而不是数组值
    }
    while(!s.empty())
        popStackSetMap(s,rBigMap);
    //构造Node数组
    Node* nArr[len];
    for(int i=0;i<len;i++)
    {
        nArr[i] = new Node(a[i]);
    }
    //构造Node的MaxTree
    Node *head = NULL;
    for(int i=0;i<len;i++)
    {
        //调试代码
        //cout << "nArr[" << i << "]->value = " << nArr[i]->value << endl;
        //cout << "lBigMap = " << lBigMap[i] << endl;
        //cout << "rBigMap = " << rBigMap[i] << endl;

        string ls = lBigMap[i];
        string rs = rBigMap[i];
        if(ls.empty() && rs.empty())
        {
            head = nArr[i];
        }
        else if(ls.empty())
        {
            stringstream ss(rs);
            int rID;
            ss >> rID;
            if(NULL == nArr[rID]->left)
                nArr[rID]->left = nArr[i];
            else
                nArr[rID]->right = nArr[i];
        }
        else if(rs.empty())
        {
            stringstream ss(ls);
            int lID;
            ss >> lID;
            if(NULL == nArr[lID]->left)
                nArr[lID]->left = nArr[i];
            else
                nArr[lID]->right = nArr[i];
        }
        else
        {
            stringstream lss(ls);
            int lID;
            lss >> lID;

            stringstream rss(rs);
            int rID;
            rss >> rID;

            int pID = a[lID] < a[rID] ? lID : rID;
            
            if(NULL == nArr[pID]->left)
                nArr[pID]->left = nArr[i];
            else
                nArr[pID]->right = nArr[i];
        }
    }
    return head;
}

int main()
{
    int a[] = {3,4,5,1,2};
    Node *head = getMaxTree(a,5);
    Node *left = head->left;
    Node *right = head->right;
    cout << "head->value = "<< head->value << endl;
    cout << head->value <<"->left->value = "<< left->value << endl;
    cout << head->value <<"->right->value = "<< right->value << endl;
    if(NULL != left->left)
        cout << left->value << "->left->value = " << left->left->value << endl;
    else 
        cout << left->value << "->left is empty!" << endl;
        
    if(NULL != left->right)
        cout << left->value << "->right->value = " << left->right->value << endl;
    else 
        cout << left->value << "->right is empty!" << endl;
    
    if(NULL != right->left)
        cout << right->value << "->left->value = " << right->left->value << endl;
    else 
        cout << right->value << "->left is empty!" << endl;
    
    if(NULL != right->right)
        cout << right->value << "->right->value = " << right->right->value << endl;
    else 
        cout << right->value << "->right is empty!" << endl;
    return 0;
}
View Code

【说明】

  1、hash_map并不属于标准的STL,但是大部分的开发环境已经将其实现。在GCC中也可直接使用,但是需要声明命名空间为 __gnu_cxx;

  2、C++中的hash_map的使用自定义的类型时,需要在类中实现hash函数和等于比较函数,所以我使用了string作为替代;

  3、在string与int类型的互换中,我使用了stringstream这一辅助类型。

  4、关键的思路还是参考了左程云老师提出的思路,具体实现有些差别,小伙伴们可以自行查看。

  5、hash_map使用方法的参考文章:

      C++ STL中哈希表 hash_map介绍

      hash_map使用自定义类型做主键

  6、测试代码未使用二叉树的遍历算法,大家就凑合着看看吧。^_^  ^_^   ^_^

 

注:

  转载请注明出处;

  转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

构造数组的MaxTree

标签:

原文地址:http://www.cnblogs.com/PrimeLife/p/5339965.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!