树(4)由先序、中序、后序序列创建二叉树以及二叉树顺序存储和链式存储的转换

同一棵二叉树(每个节点值唯一)具有唯一的先序序列、中序序列和后序序列,不同二叉树可能具有相同的先序序列、中序序列和后序序列。
同时给定先序序列和中序序列或者中序序列和后序序列都能唯一确定二叉树,但同时给定先序序列和后序序列不能唯一确定二叉树。
1.由先序和中序构建二叉树
在这里插入图片描述
由先序序列可知 a 0 a_0 a0是根节点,假设对应于 b k b_k bk,则可得左子树有k个节点,右子树有n-k-1个节点,便可以取定左右子树。采用类似的方法一直进行。

void CreatBT1(BTnode* &T,string pre,string in)
{
    if(pre.size() == 0)
    {
        T = nullptr;
        return;
    }
    int n = pre.size();
    char roots  = pre[0];//获得根节点的值
    int k = in.find(roots);//由根节点在中序的位置获得左子树的长度
    //substr函数有两个参数,第一个是开始位置,第二个是获取子串的长度
    string leftin = in.substr(0,k);//左子树中序
    string rightin = in.substr(k+1,n-k-1);//右子树中序
    string leftpre = pre.substr(1,k);//左子树先序
    string rightpre = pre.substr(k+1,n-k-1);//右子树先序

    T = (BTnode*)malloc(sizeof(BTnode));
    if(T != nullptr)
    {
        T->data = roots;
        CreatBT1(T->lnode,leftpre,leftin);
        CreatBT1(T->rnode,rightpre,rightin);
    }
}

2.由后序和中序构建二叉树
在这里插入图片描述
由后序序列可以确定根节点,由中序序列可以确定左右子树。

void CreatBT2(BTnode* &T, string post, string in){//由后序序列和中序序列确定树
    if (post.size() == 0){
        T = nullptr;
        return;
    }
    else{
        int n = post.size();
        char roots = post[n-1];//确定根节点
        int k = in.find(roots);//找出根节点在中序序列中的位置,得到左子树的长度

        string leftpost = post.substr(0,k);//左子树的后序序列
        string leftin = in.substr(0,k);//左子树的中序序列
        string rightpost = post.substr(k,n-k-1);//右子树的后序序列
        string rightin = in.substr(k+1,n-k-1);//右子树的中序序列

        T = (BTnode*)malloc(sizeof(BTnode));//创建根节点
        if (T != nullptr){
            T->data = roots;
            CreatBT2(T->lnode,leftpost,leftin);
            CreatBT2(T->rnode,rightpost,rightin);
        }

    }
}
二叉树顺序存储和链式存储的转换

例1:设计算法将二叉树的顺序存储结构转换成二叉链存储结构。
递归模型:当i大于MaxSize时,f(a,i)=NULL;当i对应的节点为空时,f(a,i)=NULL;其他情况,创建根节点b,其值为a[i],b->lchild=f(a,2i),b->rchild=f(a,2i+1)。

typedef char SqBTree[MaxSize];
BTnode* trans1(SqBTree a, int i){//将顺序存储转换为二叉链存储结构
    if (i>MaxSize) return nullptr;
    if (a[i] == '#') return nullptr;
    BTnode* b;
    b = (BTnode*)malloc(sizeof(BTnode));
    b->data = a[i];
    b->lnode = trans1(a,2*i);
    b->rnode = trans1(a,2*i+1);
    return b;
}

例2:设计算法将二叉树的二叉链转换为顺序存储结构。
f(b,a,i):由b创建a[i]为根节点的顺序存储结构a。递归模型:
当b=NULL时,a[i] = ‘#’ ;其他情况,a[i] = b->data,f(b->lchild,a,2i),f(b->rchild,a,2i+1)。

void trans2(BTnode* b, SqBTree &a, int i){//将二叉链转换为顺序存储结构
    if (b != nullptr){
        a[i] = b->data;
        trans2(b->lnode,a,2*i);
        trans2(b->rnode,a,2*i+1);
    }
    else{
        a[i] = '#';
    }
}

int main() {

    BTnode* root2;
    char s[] = "0ABCD#EF##G####################";
    root2 = trans1(s,1);
    Display(root2);
    cout << '\n' << endl;

    SqBTree a;
    trans2(root2,a,1);

    BTnode* root3;
    root3 = trans1(a,1);
    Display(root3);

	return 0;
}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用链式存储结构建立二叉树,并实现先序中序后序遍历的示例代码: ```c #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* left; struct Node* right; }; // 创建新节点 struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); if (newNode == NULL) { printf("内存分配失败!\n"); exit(1); } newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // 建立二叉树 struct Node* buildTree() { int data; struct Node* root = NULL; printf("请输入节点的值(输入-1表示空节点):"); scanf("%d", &data); if (data == -1) { return NULL; } else { root = createNode(data); printf("请输入节点 %d 的左子:\n", data); root->left = buildTree(); printf("请输入节点 %d 的右子:\n", data); root->right = buildTree(); return root; } } // 先序遍历 void preOrder(struct Node* root) { if (root != NULL) { printf("%d ", root->data); preOrder(root->left); preOrder(root->right); } } // 中序遍历 void inOrder(struct Node* root) { if (root != NULL) { inOrder(root->left); printf("%d ", root->data); inOrder(root->right); } } // 后序遍历 void postOrder(struct Node* root) { if (root != NULL) { postOrder(root->left); postOrder(root->right); printf("%d ", root->data); } } int main() { struct Node* root = NULL; int choice; while (1) { printf("\n---- 选项菜单 ----\n"); printf("1. 建立二叉树\n"); printf("2. 先序遍历\n"); printf("3. 中序遍历\n"); printf("4. 后序遍历\n"); printf("0. 退出\n"); printf("请选择操作:"); scanf("%d", &choice); switch (choice) { case 1: root = buildTree(); break; case 2: printf("先序遍历结果:"); preOrder(root); printf("\n"); break; case 3: printf("中序遍历结果:"); inOrder(root); printf("\n"); break; case 4: printf("后序遍历结果:"); postOrder(root); printf("\n"); break; case 0: printf("程序已退出。\n"); exit(0); default: printf("无效的选项,请重新选择。\n"); break; } } return 0; } ``` 在主函数中,通过一个选项菜单,可以选择执行建立二叉树先序遍历、中序遍历或后序遍历操作。建立二叉树时,按照先序输入二叉树的节点序列,输入-1表示空节点。然后,根据选择的操作,对建立的二叉树进行相应的遍历。你可以根据需要修改菜单选项及节点数据,然后编译运行该代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值