编程之美:第三章 结构之法 3.10分层遍历二叉树

来源:互联网 发布:如何从网页提取数据 编辑:程序博客网 时间:2024/05/16 19:47
/*分层遍历二叉树:1给定一颗二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号,那么分层遍历如下的二叉树,正确的输出应该为12 34 5 67 8                       12                    3 4            5                     6            7    82写另外一个函数,打印二叉树中某层次的节点(从左到右),其中根节点为第0层,函数原型为int PrintNodeAtLevel(Node* root,int level),成功返回1,失败返回0假设要求放分二叉树中第k层的节点,那么其实可以把它转换成分别访问"以该二叉树根节点的左右子节点为根节点的两棵子树"中层次为k-1的节点,如题目中的二叉树,给定k=2,即要求访问原二叉树中第2层的节点(根节点为第0层),可把它转换成分别访问以节点2,3为根节点的两棵子树中第k-1 = 1层的节点                                                              12                                                            34                              5                             0                                    06               7             8                 90        0      0       0    0         0       0          0输入:191 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0输出:1 2 34 56 7 8 9 *//*关键:1 if(!pRoot || iLevel < 0){return 0;//这个返回值,非常有用,用于无法知道树的深度的情况下,当无法遍历某一层次的输出2 if(iLevel == 0)//递归出口{printf("%d ",pRoot->_iVal);return 1;}3 return printNodeAtLevel(pRoot->_pLeft,iLevel-1) + printNodeAtLevel(pRoot->_pRight,iLevel-1);//注意返回的是当前层次下所有子节点个数4 for(int iLevel = 0 ; ; iLevel++)//效率差,每次访问都需要从根节点重新遍历{if(!printNodeAtLevel(pRoot,iLevel))//当访问到某一层次失败就可以退出了。当level小于0的时候{break;5 在访问第k层的时候,我们需要知道第k-1层的节点信息,所以再访问第k层的时候,要是知道第k-1层的节点信息,就不需要从根节点开始遍历可以从根节点除法,将每一层的节点从左到右压入一个数组,并用一个游标cur记录当前访问的节点,另一个游标last表示当前层次最后一个节点的下一个位置。以cur = last表示当前层次访问结束,在访问某一层的同时将该层所有节点的子节点压入数组,在访问完某一层之后,检查是否还有新的层次可以访问,直到访问完所有的层次。6 int iCur = 0,iLast = 1;//初始化游标起始位置和当前层结束位置的下一个位置7 while(iCur < vecNode.size())//这里应该是层结束位置等于数组大小的时候结束循环8 iLast = vecNode.size();//牛逼,直接用当前层结束位置的下一位置 等于 向量大小 来解决了每次的更新层结束位置的问题while(iCur < iLast)*/#include <stdio.h>#include <string.h>#include <vector>using namespace std;const int MAXSIZE = 10000;typedef struct Node{int _iVal;Node* _pLeft,*_pRight;}Node;Node g_nodeArr[MAXSIZE];int g_iIndex;Node* createNode(){++g_iIndex;g_nodeArr[g_iIndex]._pLeft = g_nodeArr[g_iIndex]._pRight = NULL;return &g_nodeArr[g_iIndex];}Node* buildTree(int* pArr,int iLen,int& iPos){if(!pArr || iLen < 0 || iPos < 0){return NULL;}Node* pRoot;if(pArr[iPos] == 0)//如果是叶节点{iPos++;return NULL;}if(iPos < iLen)//如果还没有超过长度,持续建立{pRoot = createNode();pRoot->_iVal = pArr[iPos++];pRoot->_pLeft = buildTree(pArr,iLen,iPos);pRoot->_pRight = buildTree(pArr,iLen,iPos);}return pRoot;}//返回的是某一层下面的节点总数int printNodeAtLevel(Node* pRoot,int iLevel){if(!pRoot || iLevel < 0){return 0;//这个返回值,非常有用,用于无法知道树的深度的情况下,当无法遍历某一层次的输出}if(iLevel == 0)//递归出口{printf("%d ",pRoot->_iVal);return 1;}return printNodeAtLevel(pRoot->_pLeft,iLevel-1) + printNodeAtLevel(pRoot->_pRight,iLevel-1);//注意返回的是当前层次下所有子节点个数}void printLevelNode_withoutDepth(Node* pRoot)//访问二叉树某一层次失败的时候返回就可以了{for(int iLevel = 0 ; ; iLevel++)//效率差,每次访问都需要从根节点重新遍历{if(!printNodeAtLevel(pRoot,iLevel))//当访问到某一层次失败就可以退出了。当level小于0的时候{break;}printf("\n");}}void printLevelNode(Node* pRoot,int iDepth){for(int i = 0 ; i < iDepth ; i++)//打印每一层的节点{printNodeAtLevel(pRoot,iDepth);}}/*在访问第k层的时候,我们需要知道第k-1层的节点信息,所以再访问第k层的时候,要是知道第k-1层的节点信息,就不需要从根节点开始遍历可以从根节点除法,将每一层的节点从左到右压入一个数组,并用一个游标cur记录当前访问的节点,另一个游标last表示当前层次最后一个节点的下一个位置。以cur = last表示当前层次访问结束,在访问某一层的同时将该层所有节点的子节点压入数组,在访问完某一层之后,检查是否还有新的层次可以访问,直到访问完所有的层次。首先将根节点1压入数组,将游标cur置为0,游标last置为1,因为当cur = last = 1时,第0层访问结束。当cur < last,说明此层尚未被访问完,因此依次访问cur到last之间的所有节点,并依次将被访问节点的左右子节点压入数组,当放完问第一层时,cur = 1,cur == last ,盖层访问完,此时数组中还有尚未被访问到的节点,则输出换行符(为输出新的一行做准备),并将Last定位与新一行的末尾(即数组当前最后一个元素的下一位),继续依次访问其他层次的节点,知道所有层次访问结束。*/void printLevelNode_index(Node* pRoot){int iCur = 0,iLast = 1;//初始化游标起始位置和当前层结束位置的下一个位置vector<Node*> vecNode;vecNode.push_back(pRoot);while(iCur < vecNode.size())//这里应该是层结束位置等于数组大小的时候结束循环{iLast = vecNode.size();//牛逼,直接用当前层结束位置的下一位置 等于 向量大小 来解决了每次的更新层结束位置的问题while(iCur < iLast){Node* pNode = vecNode[iCur];printf("%d ",pNode->_iVal);//应该先打印出当前节点值if(pNode->_pLeft){vecNode.push_back(pNode->_pLeft);}if(pNode->_pRight){vecNode.push_back(pNode->_pRight);}iCur++;}printf("\n");}}void process(){int n;while(EOF != scanf("%d",&n)){int iArr[MAXSIZE];for(int i = 0 ; i < n ; i++){scanf("%d",&iArr[i]);}int iPos = 0;g_iIndex = 0;memset(g_nodeArr,NULL,sizeof(g_nodeArr));Node* pRoot = buildTree(iArr,n,iPos);//printLevelNode_withoutDepth(pRoot);printLevelNode_index(pRoot);}}int main(int argc,char* argv[]){process();getchar();return 0;}

0 0