链式二叉树的基本操作

链式二叉树结点类型的定义

typedef char BinaryTreeDataType;

typedef struct BSTreeNode
{
    struct BSTreeNode* left;//存储左孩子的地址
    struct BSTreeNode* right;//存储右孩子的地址
    BinaryTreeDataType val;//节点的数据域
}BTNode;

二叉树的深度优先遍历

1.前序遍历 根-左子树-右子树

void PrevOrderTree(BTNode* root)
{
    if (root == NULL)
    {
        return;
    }
    printf("%c ", root->val);//访问根节点的值
    PrevOrderTree(root->left);//左边走
    PrevOrderTree(root->right);//右边走
}

2.中序遍历 左子树-根-右子树

void InOrderTree(BTNode* root)
{
    if (root == NULL)
    {
        return;
    }
    InOrderTree(root->left);//左边走
    printf("%c ", root->val);
    InOrderTree(root->right);//右边走
}

3.后序遍历 (左子树-右子树-根)

void PostOrderTree(BTNode* root)
{
    if (root == NULL)
    {
        return;
    }
    PostOrderTree(root->left);
    PostOrderTree(root->right);
    printf("%c ", root->val);

 二叉树的广度优先遍历

层序遍历

自上而下,从左往右逐层访问树的结点的过程就是层序遍历。

实现思路:这里可以借助队列来实现,先进先出的性质,先入根节点,在出根节点,同时把根节点的左右非空节点入队列,其他节点重复此过程,直到队列为空时结束。

 

void LevelOrderTree(BTNode* root)
{
    queue<BTNode*> q;//创建一个结构体指针类型队列q

    if (root == NULL)
    {
        return;
    }
    q.push(root);//入根节点
    while (!q.empty())//判断队列是否为空
    {
        BTNode* front = q.front();//front用来保存队头数据
        printf("%c ", front->val);//打印队头的值
        q.pop();//出对头节点
        if (front->left)//左节点不为空,入该节点
        {
            q.push(front->left);
        }
        if (front->right)//右节点不为空,入该节点
        {
            q.push(front->right);
        }
    }

二叉树结点的个数

求节点个数时是带有返回值的递归,可以将该问题拆解成子问题,节点为空,返回0,非空,返回左子树节点个数+右子树节点个数+1(节点本身)。

int CountTreeNode(BTNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    return CountTreeNode(root->left) + CountTreeNode(root->right) + 1;//左边节点+右边节点+自身节点等于节点个数
}

叶子结点(左右节点都为空)的个数

实现思路:也是子问题拆解问题

1.若为空,返回0。
2.若左右都为空,返回1
3.除上述两种情况外,说明该树存在子树,其叶子结点个数 = 左子树的叶子结点个数 + 右子树的叶子结点个数。

int SizeLeafNode(BTNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    if (root->left == NULL && root->right == NULL)
    {
        return 1;
    }
    return SizeLeafNode(root->left) + SizeLeafNode(root->right);//左边的叶子节点+右边的叶子节点
}

第k层结点的个数 

实现思路:相对于根结点的第k层结点的个数 = 相对于以其左孩子为根的第k-1层结点的个数 + 相对于以其右孩子为根的第k-1层结点的个数。(见图理解)

 int SizeKTreeNode(BTNode* root, int k)
{
    if (k < 1 || root == NULL)
    {
        return 0;
    }
    if (k == 1)
    {
        return 1;
    }
    return  SizeKTreeNode(root->left, k - 1) + SizeKTreeNode(root->right, k - 1);
}

值为x的结点

子问题:
   1.先判断根结点是否是目标结点。
 2.再去左子树中寻找。
 3.最后去右子树中寻找。

BTNode* FindTreeNode(BTNode* root, BinaryTreeDataType x)
{
    if (root == NULL)
    {
        return NULL;
    }
    if (root->val == x)//该节点的值与x比较
    {
        return root;
    }
    BTNode* left = FindTreeNode(root->left, x);//往左边找
    if (left)
    {
        return left;//表示左边找到了,直接返回,不去找右
    }
    BTNode* right = FindTreeNode(root->right, x);//往右边找
    if (right)
    {
        return right;
    }
    return NULL;//左右子树都没有找到

树的最大深度

子问题:
 1.若为空,则深度为0。
 2.若不为空,则树的最大深度 = 左右子树中深度较大的值 + 1

int DepthTree(BTNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    int left = DepthTree(root->left);
    int right = DepthTree(root->right);
    return left > right ? left + 1 : right + 1;//左右边高的加上1(判断二叉树是否是根)

}

 判断二叉树是否是完全二叉树

实现思路:借助一个队列

1.先入非空根节点,出根节点,同时把根节点的两个字树入队列(空节点也入)
2.其他节点重复步骤1,如果出到空节点,不在入节点。
3.继续判断队列是否为空,出队列这些节点,如果有非空节点,说明不是完全二叉树,全是空节点,则是完全二叉树。

 

bool IsComBTree(BTNode* root)
{
    queue<BTNode*> q;
    if (root != NULL)
    {
        q.push(root);
    }
    BTNode* front = NULL;
    while (!q.empty())
    {
        front = q.front();
        q.pop();
        if (front == NULL)
        {
            break;//表示出到NULL,跳出循环,不在入数据。
        }
        q.push(front->left);
        q.push(front->right);
    }
    while (!q.empty())
    {
        front = q.front();
        if (front)
        {
            return false;//表示队列里面还有非空节点
        }
        q.pop();
    }
    return true;

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值