《编程之美》上面的重建二叉树: /* * ===================================================================================== * * Filename: reBuild.c * * Description: 根据前序及中序结果,重建树的根节点 * * Version: 1.0 * Created: 2010年09月29日 21时43分39秒 * Revision: none * Compiler: gcc * * Author: name (), * Company: * * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define TREELEN 7 typedef struct NODE NODE; struct NODE { NODE * pLeft; NODE * pRight; char chValue; }; void postReBuild(char * pPreOrder, char *pInOrder, int nTreeLen, NODE ** pRoot) { if ( pPreOrder == NULL || pInOrder == NULL ) { return; } NODE *pTemp = (NODE *)malloc(sizeof(NODE)); pTemp->chValue = *pPreOrder; pTemp->pLeft = NULL; pTemp->pRight = NULL; if ( *pRoot == NULL ) { *pRoot = pTemp; } if ( nTreeLen == 1 ) { return; } /*char *pOrgInOrder = pInOrder;*/ char *pLeftEnd = pInOrder; int nLeftLen = 0; while ( *pPreOrder != *pLeftEnd ) { pLeftEnd++; nLeftLen++; } int nRightLen = 0; nRightLen = nTreeLen - nLeftLen - 1; if ( nLeftLen > 0 ) { postReBuild(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft)); } if ( nRightLen > 0 ) { postReBuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot)->pRight)); } } void reBuild(char *pPreOrder, char *pInOrder, int nTreeLen, NODE ** pRoot) { /* 检查边界条件 */ if ( pPreOrder == NULL || pInOrder == NULL ) { return; } /* 获得前序遍历的第一个节点 */ NODE * pTemp = (NODE *)malloc(sizeof(NODE)); pTemp->chValue = *pPreOrder; pTemp->pLeft = NULL; pTemp->pRight = NULL; /* 如果节点为空,把当前节点复制到根节点 */ if ( *pRoot == NULL ) { *pRoot = pTemp; } /* 如果当前树长度为1, 那么已经是最后一个节点 */ if ( nTreeLen == 1 ) { return; } /* 寻找子树长度 */ char * pOrgInOrder = pInOrder; char * pLeftEnd = pInOrder; int nTempLen = 0; /* 找到左子树的结尾 */ while ( *pPreOrder != *pLeftEnd ) { if ( pPreOrder == NULL || pLeftEnd == NULL ) { return; } nTempLen++; /* 记录临时长度,以免溢出 */ if ( nTempLen > nTreeLen ) { break; } pLeftEnd++; } /* 寻找左孩子长度 */ int nLeftLen = 0; nLeftLen = (int)(pLeftEnd - pOrgInOrder); /* 寻找右孩子树的长度 */ int nRightLen = 0; nRightLen = nTreeLen - nLeftLen - 1; /* 重建左子树 */ if ( nLeftLen > 0 ) { reBuild(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft)); } /* 重建右子树 */ if ( nRightLen > 0 ) { reBuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot)->pRight)); } } void print(NODE * pNode) { printf("%c ", pNode->chValue); } void PostOrderTraverse(NODE * pNode, void(*visit)(NODE *pNode)) { if ( pNode != NULL ) { PostOrderTraverse(pNode->pLeft, visit); PostOrderTraverse(pNode->pRight, visit); visit(pNode); } } void InOrderTraverse(NODE * pNode, void(*visit)(NODE *pNode)) { if ( pNode != NULL ) { InOrderTraverse(pNode->pLeft, visit); visit(pNode); InOrderTraverse(pNode->pRight, visit); } } void PreOrderTraverse(NODE * pNode, void(*visit)(NODE *pNode)) { if ( pNode != NULL ) { visit(pNode); PreOrderTraverse(pNode->pLeft, visit); PreOrderTraverse(pNode->pRight, visit); } } int main(int argc, char **argv) { char szPreOrder[ TREELEN ] = { 'a', 'b', 'd', 'c', 'e', 'f', '/0' }; char szInOrder[ TREELEN ] = { 'd', 'b', 'a', 'e', 'c', 'f', '/0' }; /*char szPreOrder[ TREELEN ];*/ /*char szInOrder[ TREELEN ];*/ /*scanf("%s%s", szPreOrder, szInOrder);*/ NODE *pRoot = NULL; reBuild(szPreOrder, szInOrder, TREELEN - 1, &pRoot); /*postReBuild(szPreOrder, szInOrder, TREELEN - 1, &pRoot);*/ PreOrderTraverse(pRoot, print); putchar('/n'); InOrderTraverse(pRoot, print); putchar('/n'); PostOrderTraverse(pRoot, print); putchar('/n'); return 0; } 构建二叉树,分层遍历(递归以及非递归实现),二叉树深度 /* * ===================================================================================== * * Filename: printNodeAtLevel.c * * Description: 给定一颗二叉树,要求按分层遍历二叉树,即从上到下按层次访问该二叉树 * 每一层要求访问的顺序为从左到右,并将节点依次编号 * * Version: 1.0 * Created: 2010年09月30日 13时54分44秒 * Revision: none * Compiler: g++ * * Author: name (BinQRay), * Company: * * ===================================================================================== */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <vector> using namespace std; #define N 100 typedef struct NODE NODE; struct NODE { char chValue; NODE* pLeft; NODE* pRight; }; void print(NODE * pNode) { if ( pNode->chValue != ' ' ) { printf("%c ", pNode->chValue); } } // 递归构建二叉树 void creatTree(NODE ** root) { char elem; NODE *pTemp = NULL; if ( scanf("%c", &elem) != EOF ) { pTemp = (NODE *)malloc(sizeof(NODE)); pTemp->chValue = elem; *root = pTemp; if ( elem != ' ' ) { creatTree(&((*root)->pLeft)); creatTree(&((*root)->pRight)); } else { (*root)->pLeft = NULL; (*root)->pRight = NULL; } } } // 递归实现层次遍历 int printNodeAtLevel(NODE * root, int level) { if ( root == NULL || level < 0 ) { return 0; } if ( level == 0 && root->chValue != ' ') { /*printf("%c ", root->chValue);*/ print(root); } /*return printNodeAtLevel(root->pLeft, level - 1) + printNodeAtLevel(root->pRight, level - 1);*/ // 从左到右遍历 return printNodeAtLevel(root->pRight, level - 1) + printNodeAtLevel(root->pLeft, level - 1); // 从右到左遍历 } // 求二叉树的递归深度算法 int getTreeLevel(NODE * root) { int level = 0; // 总高度 int left = 0; // 左子树高度 int right = 0; // 右子树高度 if ( root != NULL && root->chValue != ' ') // 非空树,同时数据域不为空才可以有左右子树 { level = 1; left = getTreeLevel(root->pLeft); // 获取左子树高度 right = getTreeLevel(root->pRight); // 获取右子树高度 level += left > right ? left : right; // 判断左右子树的高度 } return level; } // 非递归实现层次遍历:运用C++中的容器vec来保存每个层次自左向右的节点 void printNodeByLevel_CCVector(NODE * root) { if ( root == NULL ) { return; } vector<NODE *> vec; vec.push_back(root); int cur = 0; int last = 1; while ( cur < (int)vec.size() ) { last = vec.size(); while ( cur < last ) { /*cout << vec[ cur ]->chValue << " ";*/ print(vec[ cur ]); if ( vec[ cur ]->pLeft ) { vec.push_back(vec[ cur ]->pLeft); } if ( vec[ cur ]->pRight ) { vec.push_back(vec[ cur ]->pRight); } cur++; } cout << endl; } } // 非递归层次遍历二叉树:运用C中的指针实现 void printNodeByLevel_CPoint(NODE * root) { NODE *vec[ N ]; // N = 100; 预计有100个节点,当然这个没有C++中的容器安全,不能智能增长 int cur; int last; int size; if ( root == NULL ) { return; } cur = 0; last = 1; size = 1; vec[ 0 ] = root; while ( cur < size ) { last = size; while ( cur < last ) { /*printf("%c ", vec[ cur ]->chValue);*/ print(vec[ cur ]); if ( vec[ cur ]->pLeft != NULL ) { vec[ size++ ] = vec[ cur ]->pLeft; } if ( vec[ cur ]->pRight != NULL ) { vec[ size++ ] = vec[ cur ]->pRight; } cur++; } putchar('/n'); } } int main(int argc, char **argv) { NODE * root = NULL; int level; int i; creatTree(&root);putchar('/n'); // 构建二叉树 level = getTreeLevel(root); // 通过递归获取层次深度 printf("%d/n", level); printNodeByLevel_CCVector(root); // 通过c++的容器实现层次遍历 printNodeByLevel_CPoint(root); // 通过C语言中的指针数组实现层次遍历 for ( i = 0; i < level; i++ ) // 通过递归实现层次遍历:每次只输出level层次的值 { printNodeAtLevel(root, i);putchar('/n'); } return 0; }