二叉树的基本操作

学完了线性结构以后,接下来就要学树了,下面简要讨论一下二叉树; 1、 二叉树的定义

图1

二叉树是每个结点最多有两个孩子,且其子树有左右之分的有序树。
二叉树的递归定义

二叉树是一棵有序树,它的任一结点至多只有两个孩子,分别叫做左孩子和右孩子。根的左孩子L和右孩子R也是二叉树,称为根的左子树和右子树。
图1就是一棵二叉树。
二叉树的两个特殊形态
⑴满二叉树:
如果一棵深度为K的二叉树,共有2K-1个结点,即任意第I层有2I-1的结点,称为满二叉树。(如图2-a)
⑵完全二叉树:
如果一棵二叉树最多只有最下层但不是叶结点的度数可以小于2,并且最下层的结点如果只有一个孩子,它必须是左孩子,则称此二叉树为完全二叉树(如图2-b))
换句话说,满二叉树就是儿女双全的,每个生育了的结点都有两个孩子。完全二叉树就是虽然不满,但生育了就先生男孩(左),没有只养女儿的。图2左边是满二叉树,右边是完全二叉树。


图2

2、二叉树的基本操作:
2.1二叉树的构建:

例一:已知二叉树的一个按先序遍历输入的字符序列,如abc,,de,g,,f,,, (其中,表示空结点)。请建立二叉树并按中序和后序的方式遍历该二叉树。

void bulidTree(node *&root,char s[])
{
    root = (node *)malloc(sizeof(node));
    if(s[++l]==',')
    {
        root = NULL;
    }
    else
    {
        root->data = s[l];
        bulidTree(root->left,s);
        bulidTree(root->right,s);
    }
}
2.2二叉树的遍历 二叉树的遍历是指按照一定的顺序不重复地访问二叉树中的每一个结点。如果用L、D、R分别表示左子树、根结点、右子树,则有3种遍历方法: DLR、LDR、LRD 这三种遍历规则分别称为先序遍历、中序遍历和后序遍历(以根为标准)。所谓先序遍历是指对于每个结点,先访问根结点,然后访问左结点,最后访问右结点。以父结点为标准,父结点D在先(中,后),就叫做先(中,后)序。子结点总是以左为先的。 对于二叉树的操作常见的有根据给定的数据建树、插入和输出结点、寻根、访问结点、遍历访问、求树的高度和求最大路径等。下面我们用编程来介绍建树和遍历的算法。 建立二叉树如图三:

图3

1 . 前根序遍历:先遍历根结点,然后遍历左子树,最后遍历右子树。

ABDHECFG

2.中根序遍历:先遍历左子树,然后遍历根结点,最后遍历右子树。

HDBEAFCG

3.后根序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点。

HDEBFGCA

//先序遍历
void preorder(node *root)
{
    if(root)
    {
        cout<<root->data;
        preorder(root->left);
        preorder(root->right);
    }
}
//中序遍历
void inorder(node *root)
{
    if(root)
    {
        cout<<root->data;
        inorder(root->left);
        inorder(root->right);
    }
}
//后序遍历
void postorder(node *root)
{
    if(root)
    {
        cout<<root->data;
        postorder(root->left);
        postorder(root->right);
    }
}
//层序遍历
int cx(node *root)
{
    queue<node*> que;
    que.push(root);
    while(!que.empty())
    {
        node *temp = que.front();
        que.pop();
        if(temp!=NULL)
        {
            cout<<temp->data;
            if(temp->left)
            {
                que.push(temp->left);
            }
            if(temp->right)
            {
                que.push(temp->right);
            }
        }
    }
}

3、建立方法扩展:
3.1已知中选遍历和先序遍历构建二叉树:

先序遍历:ABDFGHIEC
中序遍历:FDHGIBEAC
求后序遍历:?


typedef struct node
{
    node *left;
    node *right;
    char data;
}node;

void bulidTree(node *&tree,char a[],char b[],int len)
{
    if(len<=0)
        tree = NULL;
    else
    {
        tree = (node *)malloc(sizeof(node));
        tree->data = a[0];
        char *p;
        for(p = b;*p!='\0';p++)
        {
            if(*p==a[0])
                break;
        }
        int k = p - b;
        bulidTree(tree->left,a+1,b,k);
        bulidTree(tree->right,a+k+1,p+1,len-k-1);
    }
}
void postorder(node *root)
{
    if(root)
    {
        cout<<root->data;
        postorder(root->left);
        postorder(root->right);
    }
}
int main()
{
    char a[100],b[100];
    int t;
    while(cin>>t)
    {
        cin>>a>>b;
        node *root;
        postorder(root);
        cout<<endl;
    }
}

3.2已知后序遍历和中序遍历求先序遍历。
中序遍历:dbgeafc
后序遍历:dgebfca
先序遍历:?

typedef struct node
{
    node *left;
    node *right;
    char data;
}node;
typedef struct node
{
    node *left;
    node *right;
    char data;
}node;

void xzTree(node *&tree,char a[],char b[],int len)
{
    if(len<=0)
        tree = NULL;
    else
    {
        tree = (node *)malloc(sizeof(node));
        tree->data = b[len-1];
        char *p;
        for(p = a;*p!='\0';p++)
        {
            if(*p==b[len-1])
                break;
        }
        int k = p - a;
        xzTree(tree->left,a,b,k);
        xzTree(tree->right,a+k+1,b+k,len-1-k);
    }
}

4.求二叉树的高度

int deep(node *tree)
{
    if(!tree)
    {
        return 0;
    }
    else
    {
        int left = deep(tree->left)+1;
        int right = deep(tree->right) +1;
        return left > right ? left:right;
    }
}

5.统计叶子节点的个数

void leaf(node *root,int &n)
{
    if(root!=NULL)
    {
        if(root->left==NULL&&root->right==NULL)
        {
            n++;
        }
        leaf(root->left,n);
        leaf(root->right,n);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值