编程之美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实现了非递归算法,用队列和栈完成对节点的层次遍历和记录,不知道有没有更好的方法。