树的实现及其基本操作

**

一:实验要求

**
实验 1 二叉树的建立及其基本运算算法
目的:理解二叉树左右指针存储结构,并基于该数据结构,掌握二叉
树各种基本运算算法的设计
内容:编写一个程序 btree_op.c 实现二叉树的基本运算,完成如下
1 有图 5.1 所示的二叉树创建对应的左右指针存储结构 t,
在这里插入图片描述
该二叉树的括号表示串为“A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”
2 输出二叉树 t
3 输出‘H’结点的左右孩子结点值
4 输出二叉树 t 的高度
5 释放二叉树 t


二:代码实现


1.结构体的定义

struct tree{  //树节点
    char val;
    struct tree* l;
    struct tree* r;
};
typedef struct tree Node;
typedef struct tree* Pnode;
typedef struct tree Tree;
typedef struct tree* Ptree;

代码分析:
1.树节点中一个数据域用来储存值,两个指针域用来分别指向左右孩子节点
2.树的创建

void creat_tree(Ptree &root,char c[]){
    int maxnum = strlen(c);//获取字符串的长度
    Ptree st[1000];  //使用字符数组模拟栈
    int top = -1;//控制栈顶元素下标
    int j = 0;//用来遍历字符串数组c
    int k = 0;//k=1:表示将处理的节点作为左节点
    Ptree node;  //用来储存新的节点
    root = NULL;
    char ch = c[j];
    while(ch != '\0'){
        switch(ch){
            case '(':{
                top++;
                st[top] = node;
                k = 1;
                break;
            }
            case ')':{
                top--;
                break;
            }
            case ',':{
                k = 2;
                break;
            }
            default:{
                node = (Ptree)malloc(sizeof(Tree));
                if(node != NULL){
                    node->val = ch;
                    node->l = NULL;
                    node->r = NULL;
                }
                if (root == NULL) {
                    root = node;
                } 
                else {
                    switch (k) {
                        case 1: {
                            st[top]->l = node;
                            break;
                        }
                        case 2: {
                            st[top]->r = node;
                            break;
                        }
                    }
                }
            }
        }
        j++;
        ch = c[j];
    }
}

代码分析:
1.接受两个参数,分别是根节点和字符串数组
2.接受到字符串数组后需要对字符串数组进行遍历,以此来确定每个字符在树中的具体位置。
3.使用变量j来控制对字符数组的遍历
4.node节点为当前处理的节点
5char ch 为字符串中正在处理的字符
6.使用变量k来确定当前处理的节点是左子树还是右子树,k=1代表将node节点作为根节点的左子树,n=2 代表将node节点作为根节点右子树。
7.Ptree st[1000]用来模拟栈,以此来使得所有的节点建立联系
8.top 可以理解为栈的栈顶元素的下标
9.栈顶元素为一棵树的根节点,node节点是用来储存新的节点的
10.因为树的定义是递归的,想要建立节点之间的关系,必须要抽象出问题的本质,在分析中,可以简单的理解为处理只有三个节点的二叉树,比较容易理解。
11.在构建树的过程中st[top]节点就可以理解为根节点,node节点为将要添加的节点,将node节点赋值之后,要判断该节点放在左子树上还是右子树上。
12.在遍历字符串的时候,c[j]只存在四种可能,(1)左括号(2)右括号(3)逗号(4)字符
14.遇见左括号时,说明根节点存在左子树,但是不一定。例如(,A)
15.遇见逗号时,说明根节点存在右子树
16.遇见右括号,说明这颗树已经处理结束,需要将栈顶元素弹出。再次强调递归!!!
17.举例说明A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))构建一颗树,
<1>c[j] = ‘A’ 扫描到这里,执行default语句,为节点node开辟空间,并将其左右子节点全部置空
<2>一开始的时候root节点为空,此时扫描到’A’,将’A‘节点作为整棵树的根节点。
<3>第一次遍历结束,j自增,ch = c[j],进入第二次遍历。
<4>此时 c[j] = ‘(‘ 说明上一次遍历的节点存在左子树,那么,将上一次的节点压入栈中,即st[++top] = node;k=1;
<5>循环结束,ch = c[++j]
<6>第三次遍历ch = ‘B’,执行default语句,开辟空间node,因为在上次循环中已经是k=1,此时需要执行第二个switch语句,st[top]->l = node,break;就把’B‘节点连接在了栈顶元素即根节点的左子树上。
<7>以此类推,就可以实现整棵树的链接。

3.显示树中的所有节点

void Disptree(Ptree root){
     if (root != NULL) {
         cout << root->val;
         if (root->l || root->r) {
             cout << "(";
             Disptree(root->l);
             if (root->r) {
                 cout << ",";
             }
             Disptree(root->r);
             cout << ")";          
        }
    }
}

代码分析

  1. 将根节点作为参数传进来
  2. 首先判断根节点是否为空,只有根节点不为空,才能显示树的内容
  3. 先将根节点的值输出,之后判断根节点是否存在左右子树,如果存在,先输出左括号,再次递归的遍历左子树
  4. 如果根节点存在右子树,需要先输出逗号,再递归的处理根节点的右子树,最后处理完所有的节点输出右括号。

5求某个节点的左子树和右子树

Ptree leftChild_link(Ptree p){
    if(p ==NULL){
        return NULL;
    }
    else{
        return p->l;
    }
}

Ptree rightChild_link(Ptree p) {
    if (p == NULL) {
        return NULL;
    } else {
        return p->r;
    }
}

代码分析:
1. 如果该节点为空,就返回空
2. 否则直接返回该节点的左子树或右子树

求某棵树的高度

int PtreeHight(Ptree t){
    int lchild;
    int rchild;
    if(t == NULL){
        return 0;
    }
    else{
        lchild = PtreeHight(t->l) ;
        rchild = PtreeHight(t->r) ;
        return (lchild > rchild) ? (lchild + 1) : (rchild + 1);
    }
}

代码分析:

  1. 将树根作为参数传递进来
  2. 定义两个变量lchild,rchild分别递归的统计左右子树的高度

返回节点值为x的节点的指针

Ptree FindNode(Ptree t,char x){
    if(t == NULL){
        return NULL;
    }
    else if(t->val == x){
        return t;
    }
    else{
        Ptree p = FindNode(t->l, x);
        if(p!=NULL){
            return p;
        }
        else
            return FindNode(t->r, x);
    }
}

释放整棵树

void DestroyBTree(Ptree root){

    if(root != NULL){
        DestroyBTree(root->l);
        DestroyBTree(root->r);
        free(root);
    }

}

三:效果展示

***在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零壹寻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值