二叉树及其基本方法实现

二叉树的创建

  • 在创建这个树时一定要以数据形式创建,若以指针形式创建,则该树一直是地址形式,没有具体的数值,在后续操作中也无法对树进行具体值的创建。
typedef struct node
{
    char data;
    struct node *lchild;
    struct node*rchild;
}*PNODE,NODE;
typedef struct TREE
{
    PNODE root;
    char ref;//用来标记为空的节点

}*PTREE,TREE;
void init(PTREE t);
void create1(PTREE ptree,NODE** t);
PNODE create2(PTREE ptree);
PNODE create3(PTREE ptree,char*str)
int main()
{
   TREE tree;
   init(&tree);
  //create1(&tree,&(&tree->root));
 (&tree)->root=create2(&tree);
 fronttraverse((&tree)->root);
}

二叉树的创建方法

方法一
  • ptree->root本身为PNODE类型,为了改变它的值必须使变量为它的引用类型,即为&(ptree->root),因此形参为PNODE类型,而形参中的t=ptree->root.
void init(PTREE t)
{
    t->root=NULL;
    t->ref='#';
}
void create1(PTREE ptree,PNODE* t)//create1(ptree,&(ptree->root));
{
    char item;
    scanf("%c",&item);

    if(ptree->ref==item)
    {
        (*t)=NULL;
    }
    else{
        (*t)=(PNODE)malloc(sizeof(NODE));
        (*t)->data=item;
        create1(ptree,&((*t)->lchild));
        create1(ptree,&((*t)->rchild));
    }
}
方法二
  • 这个创建方法形参中不含根节点,不需要改变根结点的值,而在返回值中直接将返回值返回给根节点。而else中创建的t在函数中充当该树的根节点的作用,最后将它返回给原树的根节点。
    这个方法比上个容易理解,以后可以多用这个。
PNODE create2(PTREE ptree)//ptree->root=create2(ptree);
{
    char item;
    scanf("%c",&item);
    if(ptree->ref==item)
    {
        return NULL;
    }
    else{
        PNODE t=(PNODE)malloc(sizeof(NODE));
        t->data=item;
        t->lchild=create2(ptree);
        t->rchild=create2(ptree);
        return t;
    }
}

二叉树的中序遍历

void fronttraverse(PNODE root)
{
    if(root!=NULL)
    {
         printf("%c",root->data);
    fronttraverse(root->lchild);
    fronttraverse(root->rchild);
    }

}

求二叉树的基本属性

int Size(PNODE root)//求节点数
{
    if(root==NULL)
        return 0;
    else
        return Size(root->lchild)+Size(root->rchild)+1;
}
int Height(PNODE root)//返回树的高度
{
    if(root=NULL)
        return 0;
    else{
        int lheight=Height(root->lchild);
        int rheight=Height(root->rchild);
        return(lheight>rheight?lheight:rheight)+1;
    }
}

二叉树的查询方法

  • 其中若左子树有返回值,则不需要右子树调用
PNODE search(PNODE root,char a)//查找数值返回节点
{
    if(root==NULL)
        return NULL;
    if(root->data==a)
        return root;
    PNODE p=search(root->lchild,a);
    if(p!=NULL)return p;
    return search(root->rchild,a);
    
}
PNODE parent(PNODE root,PNODE p)//查找该节点的父节点
{
    if(root==NULL||P==NULL)
        return NULL;
    if(root->lchild==p||root->rchild==p)
        return root;
    PNODE q=parent(root->lchild,p);
    if(q!=NULL)return q;
    return parent(root->rchild,p);
    
}

二叉树的拷贝和清空

void Copy(PNODE p,PNODE q)//用q来拷贝p
{
    if(q==NULL)return NULL;
    p->data=q->data;
    p->lchild=Copy(q->lchild);
    p->rchild=Copy(q->rchild);
}
void Clear(PNODE root)//清空树
{
    if(root!=NULL)
    {
        Clear(root->lchild);
        Clear(root->rchild);
        free(root);
        root=NULL;
    }
}

二叉树的非递归遍历

1.前序非递归遍历(利用链式栈):
  • 先将根节点放进栈中,再得到栈顶元素,将它取出,判断他的右子树是否为空,不为空就放进栈中,在判断左子树是否为空,不为空就放进栈中。(这块要先判断右子树再判断左子树)再次得到栈顶元素,取出输出,直至栈为空时停止循环。
void fronttraverse1(PSTACK ps,PTREE pt)//前序非递归遍历
{
    PNODE root=pt->root;
    push(ps,root->data);
    if(!is_empty(ps))
    {
        PNODE p=getpop(ps);
        pop(ps);
        printf("%c",p->data);
    if(p->rchild!=NULL)
        push(ps,p->rchild);
    if(p->lchild!=NULL)
        push(ps,p->lchild);
    }
}
2.中序非递归遍历二叉树:
  • 先通过循环得到最左下的节点,将其输出,再判断它是否有右子树,有就放入栈中,不断循环。循环终止条件是栈为空,因此循环前要将根节点先放进去,再次利用循环找到最左下的节点,之后找一个右子树,再次找到它最左下的节点。
void inordertraverse(PSTACK ps,PTREE pt)
{
    PNODE p=pt->root;
    if(p!=NULL)
    {
        push(ps,p);
        PNODE t;
    while(!is_empty(ps))
    {
        while(p!=NULL&&p->lchild!=NULL)
        {
            p=p->lchild;
            push(ps,p);
        }
        t=getpop(ps);
        printf("%c",t->data);
        pop(ps,t);
        if(t->rchild!=NULL)
        {
            push(ps,t->rchild);
        }
    }
    }   
}
4.后序非递归遍历二叉树:
  • 后序遍历时先找到最左下的节点,然后判断它右子树是否存在,有就入栈。而因为根节点是最后输出的,所以在输出时要判断是从左子树返回还是从右子树返回,因此在栈中的元素应该是一个结构体,包含了enum形式的{L,R}以及相应的节点,从左子树判断完成后,先判断栈中元素是L还是R,若是L则在判断它的右子树是否为空,若为空则输出该节点,若不为空,则进入循环继续找到最左下的节点进行判断。
void postorder(PSTACK ps,PTREE pt)
{
    PNODE p=pt->root;
    TAG T;
    while(p!=NULL)
    {
        T.tag=L;
        T.ptr=p;
        push(ps,T);
        p=p->lchild;
    }
    bool flag=true;
    while(!is_empty(ps))
    {
        TAG A=getpop(ps);
        pop(ps,A);
        r=A.ptr;
        switch(A.tag)
        {
        case L:
            A.tag=R;
            push(ps,A);
            flag=false;
            p=p->rchild;
            break;
        case R:
            printf("%c",r->data);
            break;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值