二叉树节点的最大距离

编程之美3.10节。完整代码如下:

View Code
  1 #include <iostream>
  2 #include <cassert>
  3 #include <vector>
  4 #include <fstream>
  5 #include <stack>
  6 #include <queue>
  7 using namespace std;
  8 
  9 struct Node
 10 {
 11     Node* m_lChild;
 12     Node* m_rChild;
 13     int m_nMaxLeft;
 14     int m_nMaxRight;
 15     int m_data;
 16     Node(int data=0,int nMaxLeft=0,int nMaxRight=0,Node* lChild=NULL,Node* rChild=NULL)
 17         :m_data(data),m_nMaxLeft(nMaxLeft),m_nMaxRight(nMaxRight),m_lChild(lChild),m_rChild(rChild){}
 18 };
 19 
 20 void CreateTree(Node** pNode,vector<int>::iterator &begin,vector<int>::iterator end)
 21 {
 22     if (*begin!=-1)
 23     {
 24         *pNode=new Node(*begin);
 25         if (*pNode)
 26         {
 27             if (++begin!=end)
 28             {
 29                 CreateTree(&((*pNode)->m_lChild),begin,end);
 30             }
 31             if (++begin!=end)
 32             {
 33                 CreateTree(&((*pNode)->m_rChild),begin,end);
 34             }
 35         }
 36     }
 37 }
 38 
 39 Node* CreateTree(const char* fileName)
 40 {
 41     ifstream inFile;
 42     inFile.open(fileName);
 43     int value;
 44     vector<int> vec;
 45     while (inFile>>value)
 46     {
 47         vec.push_back(value);
 48     }
 49     if (vec.empty())
 50     {
 51         return NULL;
 52     }
 53     Node* pRoot=NULL;
 54     CreateTree(&pRoot,vec.begin(),vec.end());
 55     return pRoot;
 56 }
 57 
 58 //编程之美上的递归方法
 59 void FindMaxLen(Node* pRoot,int& nMaxLen)
 60 {
 61     if (!pRoot)
 62     {
 63         return ;
 64     }
 65     if (!pRoot->m_lChild)
 66     {
 67         pRoot->m_nMaxLeft=0;
 68     }
 69     if (!pRoot->m_nMaxRight)
 70     {
 71         pRoot->m_nMaxRight=0;
 72     }
 73     if (pRoot->m_lChild)
 74     {
 75         FindMaxLen(pRoot->m_lChild,nMaxLen);
 76     }
 77     if (pRoot->m_rChild)
 78     {
 79         FindMaxLen(pRoot->m_rChild,nMaxLen);
 80     }
 81     //计算左子树最长节点的距离
 82     if (pRoot->m_lChild)
 83     {
 84         int nTmpMax=0;
 85         if (pRoot->m_lChild->m_nMaxLeft>pRoot->m_lChild->m_nMaxRight)
 86         {
 87             nTmpMax=pRoot->m_lChild->m_nMaxLeft;
 88         }
 89         else
 90         {
 91             nTmpMax=pRoot->m_lChild->m_nMaxRight;
 92         }
 93         pRoot->m_nMaxLeft=nTmpMax+1;
 94     }
 95     //计算右子树最长节点的距离
 96     if (pRoot->m_rChild)
 97     {
 98         int nTmpMax=0;
 99         if (pRoot->m_rChild->m_nMaxLeft>pRoot->m_rChild->m_nMaxRight)
100         {
101             nTmpMax=pRoot->m_rChild->m_nMaxLeft;
102         }
103         else
104         {
105             nTmpMax=pRoot->m_rChild->m_nMaxRight;
106         }
107         pRoot->m_nMaxRight=nTmpMax+1;
108     }
109     if (pRoot->m_nMaxLeft+pRoot->m_nMaxRight>nMaxLen)
110     {
111         nMaxLen=pRoot->m_nMaxLeft+pRoot->m_nMaxRight;
112     }
113 }
114 
115 //使用队列和栈的非递归方法
116 void FindMaxLen2(Node* pRoot,int& nMaxLen)
117 {
118     if (!pRoot)
119     {
120         return ;
121     }
122     stack<Node*> my_Stack;
123     queue<Node*> my_Queue;
124     my_Queue.push(pRoot);
125     //利用队列实现层次遍历树,
126     //在遍历的同时将遍历的节点
127     //压入栈
128     while(!my_Queue.empty())
129     {
130         Node* tmp=my_Queue.front();
131         my_Queue.pop();
132         my_Stack.push(tmp);
133         if (tmp->m_lChild)
134         {
135             my_Queue.push(tmp->m_lChild);
136         }
137         if (tmp->m_rChild)
138         {
139             my_Queue.push(tmp->m_rChild);
140         }
141     }
142     //跳出栈中的每一个元素,从下向上计算每一个节点
143     //的nMaxLeft和nMaxRight,有点Dp的思想
144     while(!my_Stack.empty())
145     {
146         Node* tmp=my_Stack.top();
147         my_Stack.pop();
148         if (tmp->m_lChild)
149         {
150             int nTmpMax=0;
151             if (tmp->m_lChild->m_nMaxLeft>tmp->m_lChild->m_nMaxRight)
152             {
153                 nTmpMax=tmp->m_lChild->m_nMaxLeft;
154             }
155             else
156             {
157                 nTmpMax=tmp->m_lChild->m_nMaxRight;
158             }
159             tmp->m_nMaxLeft=nTmpMax+1;
160         }
161         //计算右子树最长节点的距离
162         if (tmp->m_rChild)
163         {
164             int nTmpMax=0;
165             if (tmp->m_rChild->m_nMaxLeft>tmp->m_rChild->m_nMaxRight)
166             {
167                 nTmpMax=tmp->m_rChild->m_nMaxLeft;
168             }
169             else
170             {
171                 nTmpMax=tmp->m_rChild->m_nMaxRight;
172             }
173             tmp->m_nMaxRight=nTmpMax+1;
174         }
175         if (tmp->m_nMaxLeft + tmp->m_nMaxRight > nMaxLen)
176         {
177             nMaxLen=tmp->m_nMaxLeft+tmp->m_nMaxRight;
178         }
179     }
180 }
181 
182 //删除树的操作
183 void DestroyTree(Node*& pRoot)
184 {
185     if (!pRoot)
186     {
187         return;
188     }
189     DestroyTree(pRoot->m_lChild);
190     DestroyTree(pRoot->m_rChild);
191     delete pRoot;
192 }
193 int main()
194 {
195     int nMaxlen1=0;
196     int nMaxlen2=0;
197     Node* pRoot=CreateTree("tree.txt");
198     FindMaxLen(pRoot,nMaxlen1);
199     cout<<"nMaxlen1 = "<<nMaxlen1<<endl;
200     FindMaxLen2(pRoot,nMaxlen2);
201     cout<<"nMaxlen2 = "<<nMaxlen2<<endl;
202     DestroyTree(pRoot);
203 }

注意一下几点:

1. 方法2实现了非递归算法,用队列和栈完成对节点的层次遍历和记录,不知道有没有更好的方法。

posted @ 2012-06-18 17:56  kasuosuo  阅读(190)  评论(0编辑  收藏  举报