数据结构 - 二叉树(重构 + 遍历)

  • 写在前面

昨天有同学问到我一题关于重构二叉树的问题(link),做了一下,也做个记录吧!

所谓二叉树的重构,就是给你前序和中序,或者中序和后序,让你还原这棵二叉树.

注意:给出前序和后序是不能唯一确定一棵二叉树的,证明请看这儿.

一.给出前序和中序,重构二叉树

一个递归的过程:

当前结点的value:每一轮根据前序的第一个元素确定当前结点值.

左子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,左部分即为左子树的中序遍历数组.

右子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,右部分即为右子树的中序遍历数组.

左子树的前序遍历数组:pre[1 ... i] (i为左子树的中序遍历数组的个数).

右子树的前序遍历数组:pre[i+1 ... end](i为左子树的中序遍历数组的个数).

构造出这5个值,继续递归求左右子树即可.

题目1:重建二叉树(剑指offer)

给出前序和中序,要你重建二叉树.

按照上面所说递归即可,详见代码:

/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
*       Author: crazyacking
*       Date  : 2016-01-03-21.09
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);

/**
* Definition for binary tree
* struct TreeNode {
*     int val;
*     TreeNode *left;
*     TreeNode *right;
*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

struct TreeNode
{
   int val;
   TreeNode *left;
   TreeNode *right;
   TreeNode(int x) : val(x),left(NULL),right(NULL) {}
};

class Solution
{
public:
   vector<int> tpr;
   vector<int> tin;
   void reBuild(int a,int b,int n,TreeNode *treeNode)
   {
       if(n==1) // leaf node
       {
           treeNode = new TreeNode(tpr[a]);
           return ;
       }
       else if(n<=0) // null node
           return ;
       int i=0;
       for(; tpr[a]!=tin[b+i]; ++i);
       TreeNode *lson,*rson;
       reBuild(a+1,b,i,lson);
       reBuild(a+1+i,b+1+i,n-i-1,rson);
       treeNode = new TreeNode(tpr[a]);
       treeNode->left=lson;
       treeNode->right=rson;
   }
   struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in)
   {
       tpr.clear();
       tin.clear();

for(int i=0; i<pre.size(); ++i)
           tpr.push_back(pre[i]);
       for(int i=0; i<in.size(); ++i)
           tin.push_back(in[i]);

TreeNode *root;
       int n=pre.size();
       reBuild(0,0,n,root);
       return root;
   }
};

void DFS(TreeNode *root)
{
   if(root)
   {
       cout<<(root->val)<< " ";
   }
   else return ;
   if(root->left)
       DFS(root->left);
   if(root->right)
       DFS(root->right);
}

int main()
{
   freopen("D:\\Desktop\\in.txt","r",stdin);
   int n;
   vector<int>pre;
   vector<int>in;
   while(cin>>n)
   {
       pre.clear();
       in.clear();
       for(int i=0; i<n; ++i)
       {
           int tmp;
           cin>>tmp;
           pre.push_back(tmp);
       }
       for(int i=0; i<n; ++i)
       {
           int tmp;
           cin>>tmp;
           in.push_back(tmp);
       }
       Solution a;
       TreeNode *root=a.reConstructBinaryTree(pre,in);
       DFS(root);
   }
   return 0;
}

题目2:HDU 1710 Binary Tree Traversals

方法一:也很简单,根据上面说的方法递归建树,然后按照后序访问输出即可.

/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
*       Author: crazyacking
*       Date  : 2016-01-04-18.01
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);

int n;
vector<int> pr;
vector<int> in;

struct TreeNode
{
     int val;
     TreeNode *left,*right;
     TreeNode(int v):val(v),left(NULL),right(NULL){}
};

TreeNode* reBuildBinaryTree(vector<int> pr,vector<int> in)
{
     if(pr.size()==0 || in.size()==0)
           return NULL;
     int root=pr[0];
     TreeNode *node=new TreeNode(root);
     vector<int> prLeft,prRight,inLeft,inRight;
     int i=0;
     for(;pr[0]!=in[i];++i);

for(int j=0;j!=i;++j)
           inLeft.push_back(in[j]);
     for(int j=i+1;j<in.size();++j)
           inRight.push_back(in[j]);
     for(int j=1;j<i+1;++j)
           prLeft.push_back(pr[j]);
     for(int j=i+1;j<pr.size();++j)
           prRight.push_back(pr[j]);

node->left=reBuildBinaryTree(prLeft,inLeft);
     node->right=reBuildBinaryTree(prRight,inRight);
     return node;
}

vector<int>po;
void getPostOrder(TreeNode *root,bool flag)
{
     if(root->left)
           getPostOrder(root->left,0);
     if(root->right)
           getPostOrder(root->right,0);
     po.push_back(root->val);
}
int main()
{
     while(cin>>n)
     {
           int tmp;
           pr.clear();
           in.clear();
           po.clear();
           for(int i=0;i<n;++i)
           {
                 cin>>tmp;
                 pr.push_back(tmp);
           }
           for(int i=0;i<n;++i)
           {
                 cin>>tmp;
                 in.push_back(tmp);
           }
           TreeNode *root=reBuildBinaryTree(pr,in);
           getPostOrder(root,1);
           for(int i=0;i<n;++i)
           {
                 if(i<n-1) cout<<po[i]<<" ";
                 else cout<<po[i]<<endl;
           }
     }
     return 0;
}

方法二:由于题目没让重构二叉树,只让输出后序访问的顺序,因此可直接访问输出.

/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
*       Author: crazyacking
*       Date  : 2016-01-04-20.09
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);

int n;
vector<int> pr; // pre Order
vector<int> in; // in Order
vector<int> po; // post Order

void getPostOrder(int a,int b,int n,bool flag)
{
     if(n==1)
     {
           po.push_back(pr[a]);
           return;
     }
     else if(n<=0)
           return;
     int i=0;
     for(;pr[a]!=in[b+i];++i);
     getPostOrder(a+1,b,i,false);
     getPostOrder(a+i+1,b+i+1,n-i-1,false);
     po.push_back(pr[a]);
}

int main()
{
     while(cin>>n)
     {
           pr.clear();
           in.clear();
           po.clear();
           for(int i=0;i<n;++i)
           {
                 int tmp;
                 cin>>tmp;
                 pr.push_back(tmp);
           }
           for(int i=0;i<n;++i)
           {
                 int tmp;
                 cin>>tmp;
                 in.push_back(tmp);
           }

getPostOrder(0,0,n,true);
           for(int i=0;i<n;++i)
           {
                 if(i<n-1)
                       cout<<po[i]<<" ";
                 else cout<<po[i]<<endl;
           }
     }
     return 0;
}

一.给出后序和中序,重构二叉树

/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
*       Author: crazyacking
*       Date  : 2016-01-03-21.09
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);

/**
* Definition for binary tree
* struct TreeNode {
*     int val;
*     TreeNode *left;
*     TreeNode *right;
*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

struct TreeNode
{
   int val;
   TreeNode *left;
   TreeNode *right;
   TreeNode(int x) : val(x),left(NULL),right(NULL) {}
};

class Solution
{
public:
   vector<int> tpr;
   vector<int> tin;
   void reBuild(int a,int b,int n,TreeNode *treeNode)
   {
       if(n==1) // leaf node
       {
           treeNode = new TreeNode(tpr[a]);
           return ;
       }
       else if(n<=0) // null node
           return ;
       int i=0;
       for(; tpr[a]!=tin[b+i]; ++i);
       TreeNode *lson,*rson;
       reBuild(a+1,b,i,lson);
       reBuild(a+1+i,b+1+i,n-i-1,rson);
       treeNode = new TreeNode(tpr[a]);
       treeNode->left=lson;
       treeNode->right=rson;
   }
   struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in)
   {
       tpr.clear();
       tin.clear();

for(int i=0; i<pre.size(); ++i)
           tpr.push_back(pre[i]);
       for(int i=0; i<in.size(); ++i)
           tin.push_back(in[i]);

TreeNode *root;
       int n=pre.size();
       reBuild(0,0,n,root);
       return root;
   }
};

void DFS(TreeNode *root)
{
   if(root)
   {
       cout<<(root->val)<< " ";
   }
   else return ;
   if(root->left)
       DFS(root->left);
   if(root->right)
       DFS(root->right);
}

int main()
{
   freopen("D:\\Desktop\\in.txt","r",stdin);
   int n;
   vector<int>pre;
   vector<int>in;
   while(cin>>n)
   {
       pre.clear();
       in.clear();
       for(int i=0; i<n; ++i)
       {
           int tmp;
           cin>>tmp;
           pre.push_back(tmp);
       }

/**
       * reverse pre
       *
       */
       reverse(pre.begin(),pre.end());

for(int i=0; i<n; ++i)
       {
           int tmp;
           cin>>tmp;
           in.push_back(tmp);
       }
       Solution a;
       TreeNode *root=a.reConstructBinaryTree(pre,in);
       DFS(root);
   }
   return 0;
}

时间: 2024-10-02 07:50:32

数据结构 - 二叉树(重构 + 遍历)的相关文章

Java数据结构-二叉树及其遍历

二叉树的定义:n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互相不相交的.分别称为根结点的左子树和右子树的二叉树组成. 二叉树的特点: 0<=度<=2: 左右子树是有顺序的,不能颠倒: 不论有几棵子树,也要区分它是左子树还是右子树. 二叉树的五种基本形态: 空二叉树: 只有一个根结点: 根结点只有左子树: 根结点只有右子树: 根结点既有左子树又有右子树. 举例3个结点的二叉树的形态有: 下面说一些特殊的二叉树. 斜树:所有的结点都只有左子树的二叉

数据结构——二叉树的遍历

"树"是一种重要的数据结构,本文浅谈二叉树的遍历问题,採用C语言描写叙述. 一.二叉树基础 1)定义:有且仅有一个根结点,除根节点外,每一个结点仅仅有一个父结点,最多含有两个子节点,子节点有左右之分. 2)存储结构 二叉树的存储结构能够採用顺序存储,也能够採用链式存储,当中链式存储更加灵活. 在链式存储结构中,与线性链表类似,二叉树的每一个结点採用结构体表示,结构体包括三个域:数据域.左指针.右指针. 二叉树在C语言中的定义例如以下: struct BiTreeNode{ int c;

数据结构 - 二叉树的遍历

中序遍历二叉树 1 递归算法 算法的递归定义是: 若二叉树为空,则遍历结束:否则 ⑴ 中序遍历左子树(递归调用本算法): ⑵ 访问根结点: ⑶ 中序遍历右子树(递归调用本算法). 中序遍历的递归算法 void InorderTraverse(BTNode *T) { if (T==NULL) return: InorderTraverse(T->Lchild) ; visit(T->data) ; /* 访问根结点 */ InorderTraverse(T->Rchild) ; } 2

[转]数据结构 二叉树的遍历

/********************************************************************** 二叉树的基本操作 (1)二叉树的数据结构 (2)二叉树的构造 (3)二叉树遍历 :先序,中序,后序 ************************************************************************/ #include <cstdio> #include <cstdlib> const int

数据结构-二叉树的遍历(类C语言描写叙述)

遍历概念 所谓遍历(Traversal)是指沿着某条搜索路线.依次对树中每一个结点均做一次且仅做一次訪问.訪问结点所做的操作依赖于详细的应用问题. 遍历是二叉树上最重要的运算之中的一个,是二叉树上进行其他运算之基础. 遍历方案 1.遍历方案 从二叉树的递归定义可知,一棵非空的二叉树由根结点及左.右子树这三个基本部分组成.因此.在任一给定结点上,能够按某种次序运行三个操作: (1)訪问结点本身(N), (2)遍历该结点的左子树(L), (3)遍历该结点的右子树(R). 以上三种操作有六种运行次序:

数据结构——二叉树层序遍历

层序遍历,即宽度优先遍历,在本算法中,我们还需要将每一层进行分开打印, 对于上图所示的二叉树,我们希望打印出的结果是: 1 2 3 4 5 6 7 8 首先,我们看一下二叉树节点是什么样的: class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } 具体实现中,我们采用last表示当前打印的行的最后一个元素的引用

数据结构——二叉树遍历之“递归与非递归遍历”

简述 二叉树的遍历分为先序遍历.中序遍历和后序遍历.如下图所示: 递归遍历 private void bianli1(List<Integer> list, TreeNode root) { // 先序遍历 if (root == null) { return; } list.add(root.val); bianli1(list, root.left); bianli1(list, root.right); } private void bianli2(List<Integer>

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int

[数据结构]二叉树创建与遍历

实验报告:二叉树创建与遍历 一.问题描述 二叉树是一种实用范围很广的非线性结构,一棵非空二叉树有也只有一个根结点,每个结点最多有两个子树,我们称为左子树与右子树,当一个结点的左.右子树都是空的时,沃恩称此结点为叶子结点. 二叉树有一些很好的性质,这里不再赘述.考虑如何存储一棵树,本实验选择使用链式存储结构——二叉链表:如果事先知道需要存储的二叉树是满二叉树或者完全二叉树,则可以考虑使用顺序存储,否则将浪费大量的存储空间. 对于一棵既成的二叉树,有三种遍历方式——先序.中序与后序.可以证明,一棵形

数据结构二叉树——建立二叉树、中序递归遍历、非递归遍历、层次遍历

数据结构二叉树-- 编写函数实现:建立二叉树.中序递归遍历.借助栈实现中序非递归遍历.借助队列实现层次遍历.求高度.结点数.叶子数及交换左右子树. ("."表示空子树) #include<stdio.h> #include<stdlib.h> //***********二叉树链表节点结构 typedef char DataType; typedef struct Node {  DataType data;  struct Node*LChild;  struc