C++ 输入数组利用递归建立二叉树——层序、前序、中序、后序

C++ 输入数组利用递归建立二叉树——层序、前序、中序、后序


1、输入数组要求
数组是按照遍历方式输入,当该结点为空时,用‘#’代替空的位置,如下图。(这里直接截取大话数据结构里面的图片) C++ 输入数组利用递归建立二叉树——层序、前序、中序、后序_第1张图片

2、二叉树结构定义

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

3、二叉树构建函数

// 1、层序递归创建
层序创建:根据二叉树每层节点都有左右孩子,其左右孩子对于下层又分别存在左右孩子的一个递归关系,直到最底层。

#include 
#include 
using namespace std;

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

//参数(输入数组,数组当前位置,数组长度,当前节点结构体指针指向的地址)
void CreateBiTree(int *S,int sub,int len,TreeNode* &tree){
    if((S[0]=='#')||len==0)//对特殊情况进行分析,例如输入空数组,或者'#'开头的数组
        return ;
    if(sub>=len) //超过数组长度返回
        return ;
    if(S[sub]=='#'){
        tree=NULL;
    }
    else{
        tree=(TreeNode*)malloc(sizeof(TreeNode));
        tree->val=(S[sub]);
        CreateBiTree(S,sub*2+1,len,tree->left);  //建立左子树
        CreateBiTree(S,sub*2+2,len,tree->right); //建立右子树
    }
}

void Print(TreeNode* p)
{
    if (NULL == p)
        return;
    cout<<" "<val;   
    //前序输出  1 2 4 3
    Print(p->left);
    Print(p->right);
}

int main()
{
    TreeNode* root;
    int data[] = { 1,2,3,'#',4};
    int len=sizeof(data)/sizeof(int);
    int sub=0;
    CreateBiTree(data,sub,len,root);
    Print(root);
    return 0;
}

// 2、前序递归创建
输入前序数据创建:前序遍历相对简单,与前序遍历一致,只是在遍历打印的地方改为生成节点、赋值操作。
需要注意在 CreateBiTree(int S,int &sub,int len,TreeNode &tree) 函数中参数&sub需要传入指针地址,在递归中len值必须保持调用一次增长一次。

#include 
#include 
using namespace std;
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

void CreateBiTree(int *S,int &sub,int len,TreeNode* &tree){
    if((S[0]=='#')||len==0) //对特殊情况进行分析,例如输入空数组,或者'#'开头的数组
        return ;
    if(sub>=len) //超过数组长度
        return ;
    if(S[sub]=='#')
    {
        tree=NULL;
    }
    else{
        tree=(TreeNode*)malloc(sizeof(TreeNode));
        tree->val=(S[sub]);
        CreateBiTree(S,++sub,len,tree->left);  //建立左子树
        CreateBiTree(S,++sub,len,tree->right); //建立右子树
    }
}

void Print(TreeNode* p)
{
    if (NULL == p)
        return;
    cout << " "<val; //前序输出  1 2 4 3
    Print(p->left);
    Print(p->right);
}

int main()
{
    TreeNode* root;
    int data[] = { 1, 2,'#',4,'#','#',3,'#','#'};
    int len=sizeof(data)/sizeof(int);
    int *sub,a=0;
    sub=&a;
    CreateBiTree(data,*sub,len,root);
    Print(root); 
    return 0;
}

// 3、后序递归创建
输入后序数据创建:对于前序、中序、后序三种遍历二叉树的方法只用改动打印与遍历左右子树位置修改下皆可以;那是不是创建也是如此?
下面进行分析下:对于同样的二叉树,
 前序创建输入数据 data[] = { 1, 2,’#’,4,’#’,’#’,3,’#’,’#’}
 中序创建输入数据 data[] = {’#’,2,’#’,4,’#’,1,’#’,3,’#’}
 后序创建输入数据 data[] = { ‘#’,’#’,’#’,4, 2,’#’,’#’,3,1}
可以看书中序、后序都是搜索到空才返回,所以都是’#‘开头的输入,对于下述if语句中,程序开始运行 tree=NULL;成立程序直接异常结束,就算加入判断机制跳过’#’,此时树也改变了。

   if(S[sub]=='#')
    {
        tree=NULL;
    }

对于此那输入后序数据是否不能创建了,通过分析其输入数据中可以发现,数据从后面逆着看是按照
根结点 -> 右结点 ->左节点 的顺序。我们可以参照前序遍历的方法将构建右子书与左子树顺序改变,并将输入数据顺序逆着输入即可创建出所需二叉树。

#include 
#include 
using namespace std;
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

void CreateBiTree(int *S,int &sub,int len,TreeNode* &tree){
    if((S[len]=='#')||len==0) //对特殊情况进行分析,例如输入空数组,或者'#'开头的数组
        return ;
    if(sub<=0) //超过数组长度
        return ;
    if(S[sub]=='#')
    {
        tree=NULL;
    }
    else{
        tree=(TreeNode*)malloc(sizeof(TreeNode));
        tree->val=(S[sub]);
        CreateBiTree(S,--sub,len,tree->right);  //建立右子树
        CreateBiTree(S,--sub,len,tree->left);   //建立左子树
    }
}

void Print(TreeNode* p)
{
    if (NULL == p)
        return;
    cout << " "<val;  //前序输出  1 2 4 3
    Print(p->left);
    Print(p->right);

}

int main()
{
    TreeNode* root;
    int data[] = { '#','#','#',4, 2,'#','#',3,1};
    int len=sizeof(data)/sizeof(int);
    int *sub,a=len-1;
    sub=&a;
    CreateBiTree(data,*sub,len,root);
    Print(root);
    return 0;
}

// 4、中序递归创建
输入中序数据创建:中序输入数据 data[] = {’#’,2,’#’,4,’#’,1,’#’,3,’#’}
中序递归创建放在最后是因为目前暂时没有找到合适方法进行创建。
分析原因如下:
  一、对于数据 中序输入数据其开头是遍历到左子树为空才开始返回,结尾是遍历到右子树为空才开始返回,所以数据前后都是#’,与分析后序创建时一样。对于下述if语句中,程序开始运行 tree=NULL;成立程序直接异常结束,中序前后都是所以逆序也无法创建。
  二、对于中序输入数据 data[] = {’#’,2,’#’,4,’#’,1,’#’,3,’#’} 
  我们可以试着画出二叉树:C++ 输入数组利用递归建立二叉树——层序、前序、中序、后序_第2张图片
  可见画出的两组二叉树都满足中序输入要求,中序遍历的数据不可以确定唯一一棵二叉树,怎么来创建出来一棵唯一的树。


* 至此,四种基本构建二叉树的方法分析完,大家对中间代码或者分析有意见的可以评论区留言,不知道中序输入数据有没有人可以构建出来。。。

你可能感兴趣的:(C++,C++,二叉树构建)