思路:
(1)需要了解前序遍历和和中序遍历的特点,前序遍历第一个元素即为根节点,然后再在中序遍历以这个根节点为界限得到宏观上的左子串和右子串,如下图
(2)又可以将截取的子串分为新的子串问题,从而可以通过迭代来解决,
(3)构建左子树:主要就是指针的运用,获取前序遍历左子串的起始地址和子串长度,中序遍历左子串起始位置和根节点位置
root->left = ConstructCore(preStart+1,leftPreOrderEnd, inStart,rootInorder-1);
(4)同理可得右子树
root->right = ConstructCore(leftPreOrderEnd+1,preEnd,rootInorder+1,inEnd);
1 #include <stdio.h> 2 #include <stdlib.h> 3 /*剑指offer第6个问题 4 根据前序和中序遍历来重建二叉树 5 */ 6 //定义二叉树结构 7 typedef struct BiTreeNode 8 { 9 char data; 10 struct BiTreeNode *left; 11 struct BiTreeNode *right; 12 }BiTreeNode; 13 //重建核心函数,前序的子串起始位置和中序子串的起始位置 14 BiTreeNode* ConstructCore(int *preStart,int *preEnd,int *inStart,int *inEnd); 15 //重建函数 输入前序遍历和中序遍历的首位置,长度 16 BiTreeNode* Construct(int *preOrder,int *inOrder,int length) 17 { 18 //安全性检查 19 if(preOrder==NULL||inOrder==NULL||length<0) 20 { 21 printf("Error input!\n"); 22 return 0; 23 } 24 //开始进行核心组件的迭代, 25 return ConstructCore(preOrder,preOrder+length-1, 26 inOrder,inOrder+length-1); 27 } 28 29 BiTreeNode* ConstructCore(int *preStart,int *preEnd, 30 int *inStart,int *inEnd) 31 { 32 //前序遍历的第一个元素为根节点 33 int rootValue = preStart[0]; 34 35 // printf("%d ",rootValue); 36 //构建起始节点 37 BiTreeNode* root = (BiTreeNode*)malloc(sizeof(BiTreeNode)); 38 root->data = rootValue; 39 root->left = root->right = NULL; 40 41 42 //次数遍历到最后一个元素 43 if(preStart==preEnd) 44 { 45 if(inStart==inEnd && *preStart==*inStart) 46 return root; 47 else {printf("输入错误!\n"); return 0;} 48 } 49 /*迭代前序遍历找根节点,中序遍历*/ 50 //在中序遍历中找到根节点 51 int *rootInorder = inStart; 52 while(*rootInorder!=rootValue&&rootInorder<inEnd) 53 {rootInorder++;} 54 55 // if(rootInorder==inEnd && *rootInorder!==rootValue) 56 // { 57 // printf("输入错误!\n"); 58 // return 0; 59 // } 60 //左子串的地址偏移长度 61 int leftLength = rootInorder-inStart; 62 //左子串的前序遍历截止地址 63 int *leftPreOrderEnd = preStart+leftLength; 64 //开始递归构建 65 if(leftLength>0) 66 { 67 //构建左子树 输入为前序遍历子串的起始地址,中序遍历子串的起始地址 68 root->left = ConstructCore(preStart+1,leftPreOrderEnd, 69 inStart,rootInorder-1); 70 } 71 if(leftLength<preEnd-preStart) 72 { 73 //构建右子树,输入为前序遍历子串的起始地址,中序遍历子串的起始地址 74 root->right = ConstructCore(leftPreOrderEnd+1,preEnd, 75 rootInorder+1,inEnd); 76 } 77 return root; 78 } 79 80 //打印后续遍历二叉树的结果 81 82 void lastOrderTraverse(BiTreeNode *root){ 83 if(root){ 84 lastOrderTraverse(root->left); 85 lastOrderTraverse(root->right); 86 printf("%d ",root->data); 87 } 88 } 89 90 91 92 int main(int argc,char *argv[]) 93 { 94 95 int preorder[] = {1,2,4,7,3,5,6,8}; 96 int inorder[] = {4,7,2,1,5,3,8,6}; 97 int length = sizeof(preorder)/sizeof(int); 98 BiTreeNode *t = Construct(preorder,inorder,length); 99 printf("后序遍历结果为:\n") 100 lastOrderTraverse(t); 101 102 return 0; 103 }
时间: 2024-10-19 14:08:14