二叉树基础知识:
《大话数据结构》— “ 二叉树的遍历”
二叉树基础知识总结
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路:
- 首先依据前序遍历确定根结点。
- 然后从中序遍历中找到该节点。
- 则该节点左边为根结点的左子树元素,该节点的右边为根结点的右子树元素。
- 依次类推,采用递归思想,分别在左子树、右子树,重复步骤1、步骤2、步骤3。
思路图解:
代码:
通过不同的写法,熟悉Python类和对象之间的调用风格
写法1:
class TreeNode():
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def reContructBinaryTree(pre, tin):
if len(pre) == 0:
return None
root = TreeNode(pre[0])
i = tin.index(pre[0])
root.left = reContructBinaryTree(pre[1:i+1], tin[:i])
root.right = reContructBinaryTree(pre[i+1:], tin[i+1:])
return root
def Print_res(root,lists):
temp = root
if root == None:
return lists
Print_res(temp.left, lists)
Print_res(temp.right, lists)
lists.append(temp.val)
return lists
def main():
lists = []
pre = [1, 2, 4, 7, 3, 5, 6, 8]
tin = [4, 7, 2, 1, 5, 3, 8, 6]
root = reContructBinaryTree(pre, tin)
print(Print_res(root, lists))
if __name__ == "__main__":
main()
结果为:[7, 4, 2, 5, 8, 6, 3, 1]
写法2:
class TreeNode():
def __init__(self, val):
self.val = val
self.left = None
self.right = None
class Solution():
def reContructBinaryTree(self, pre, tin):
if len(pre) == 0:
return None
root = TreeNode(pre[0])
i = tin.index(pre[0])
root.left = self.reContructBinaryTree(pre[1:i+1], tin[:i])
root.right = self.reContructBinaryTree(pre[i+1:], tin[i+1:])
return root
def Print_res(self, root, lists):
temp = root
if root == None:
return lists
self.Print_res(temp.left, lists)
self.Print_res(temp.right, lists)
lists.append(temp.val)
return lists
def main(self):
lists = []
pre = [1, 2, 4, 7, 3, 5, 6, 8]
tin = [4, 7, 2, 1, 5, 3, 8, 6]
root = self.reContructBinaryTree(pre, tin)
print(self.Print_res(root, lists))
if __name__ == "__main__":
s = Solution()
s.main()
结果为:[7, 4, 2, 5, 8, 6, 3, 1]
写法3:
class TreeNode():
def __init__(self, val):
self.val = val
self.left = None
self.right = None
class Solution():
def reContructBinaryTree(self, pre, tin):
if len(pre) == 0:
return None
root = TreeNode(pre[0])
i = tin.index(pre[0])
root.left = self.reContructBinaryTree(pre[1:i+1], tin[:i])
root.right = self.reContructBinaryTree(pre[i+1:], tin[i+1:])
return root
def Print_res(self, root, lists):
temp = root
if root == None:
return lists
self.Print_res(temp.left, lists)
self.Print_res(temp.right, lists)
lists.append(temp.val)
return lists
if __name__ == "__main__":
lists = []
pre = [1, 2, 4, 7, 3, 5, 6, 8]
tin = [4, 7, 2, 1, 5, 3, 8, 6]
s = Solution()
root = s.reContructBinaryTree(pre, tin)
print(s.Print_res(root, lists))
结果为:[7, 4, 2, 5, 8, 6, 3, 1]
C++代码:
#include <iostream>
#include <deque>
using namespace std;
//二叉树结点定义
typedef struct BiTreeNode{
int data;
//左右孩子指针
struct BiTreeNode *lchild;
struct BiTreeNode *rchild;
}BiTreeNode,*BiTree;
//访问函数
void Visit(BiTree T)
{
if(T->data != -1)
cout<<T->data<<" ";
}
//先序遍历
void PreOrder(BiTree T)
{
if(T != NULL)
{
//访问根节点
Visit(T);
//访问左子结点
PreOrder(T->lchild);
//访问右子结点
PreOrder(T->rchild);
}
}
//中序遍历
void InOrder(BiTree T)
{
if(T != NULL)
{
//访问左子结点
InOrder(T->lchild);
//访问根节点
Visit(T);
//访问右子结点
InOrder(T->rchild);
}
}
//后序遍历
void PostOrder(BiTree T)
{
if(T != NULL)
{
//访问左子结点
PostOrder(T->lchild);
//访问右子结点
PostOrder(T->rchild);
//访问根节点
Visit(T);
}
}
BiTree constructor(int * startP,int * endP,int * startI,int * endI)
{
//前序遍历序列的第一个数字是根节点的值
int rootValue=startP[0];
BiTree root;
root = (BiTree)malloc(sizeof(BiTreeNode));
root->data=rootValue;
root->lchild=root->rchild=NULL;
if(startP==endP)
{
if(startI==endI && *startP==*startI)
return root;
else
return NULL;
}
//在中序遍历中找到根节点的值
int * rootI=startI;
while(rootI<=endI && *rootI!=rootValue)
++rootI;
if(rootI==endI && *rootI!=rootValue)
return NULL;
int leftlen=rootI-startI;
int *leftPE=startP+leftlen;
if(leftlen>0)
{
//构建左子树
root->lchild=constructor(startP+1,leftPE,startI,rootI-1);
}
if(leftlen<endP-startP)
{
//构建右子树
root->rchild=constructor(leftPE+1,endP,rootI+1,endI);
}
return root;
}
BiTree foo(int * pre,int * ino,int len)
{
if(pre==NULL || ino==NULL ||len<=0)
return NULL;
return constructor(pre,pre+len-1,ino,ino+len-1);
}
void main()
{
int pre[]={1,2,4,7,3,5,6,8};
int ino[]={4,7,2,1,5,3,8,6};
int len=sizeof(pre)/sizeof(pre[0]);
BiTree T = foo(pre,ino,len);
cout<<"二叉树根节点:";
cout<<T->data<<endl;
cout<<"先序遍历:";
PreOrder(T);
cout<<endl;
cout<<"中序遍历:";
InOrder(T);
cout<<endl;
cout<<"后序遍历:";
PostOrder(T);
cout<<endl;
}
C++风格实现:剑指offer 面试题6—重建二叉树