链式二叉树的基本操作

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

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;

链式二叉树基本操作包括创建、遍历、插入、删除等。 下面是C语言实现链式二叉树基本操作示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树结构体 typedef struct TreeNode{ int data; struct TreeNode *left; struct TreeNode *right; }TreeNode, *Tree; // 创建二叉树 void createTree(Tree *t){ int data; scanf("%d", &data); if(data == -1){ // 输入-1表示该节点为空 *t = NULL; }else{ *t = (Tree)malloc(sizeof(TreeNode)); (*t)->data = data; createTree(&((*t)->left)); // 递归创建左子 createTree(&((*t)->right)); // 递归创建右子 } } // 先序遍历 void preOrder(Tree t){ if(t != NULL){ printf("%d ", t->data); preOrder(t->left); preOrder(t->right); } } // 中序遍历 void inOrder(Tree t){ if(t != NULL){ inOrder(t->left); printf("%d ", t->data); inOrder(t->right); } } // 后序遍历 void postOrder(Tree t){ if(t != NULL){ postOrder(t->left); postOrder(t->right); printf("%d ", t->data); } } // 插入节点 void insert(Tree t, int data){ if(t == NULL){ t = (Tree)malloc(sizeof(TreeNode)); t->data = data; t->left = NULL; t->right = NULL; }else{ if(data < t->data){ insert(t->left, data); }else{ insert(t->right, data); } } } // 查找节点 Tree search(Tree t, int data){ if(t == NULL){ return NULL; }else{ if(data == t->data){ return t; }else if(data < t->data){ return search(t->left, data); }else{ return search(t->right, data); } } } // 删除节点 Tree delete(Tree t, int data){ Tree p = t, q = NULL; while(p != NULL && p->data != data){ q = p; if(data < p->data){ p = p->left; }else{ p = p->right; } } if(p == NULL){ // 没有找到要删除的节点 return t; } if(p->left == NULL){ // 要删除的节点没有左子 if(q == NULL){ // 要删除的节点是根节点 t = p->right; }else if(p == q->left){ // 要删除的节点是其父节点的左子节点 q->left = p->right; }else{ // 要删除的节点是其父节点的右子节点 q->right = p->right; } free(p); }else if(p->right == NULL){ // 要删除的节点没有右子 if(q == NULL){ // 要删除的节点是根节点 t = p->left; }else if(p == q->left){ // 要删除的节点是其父节点的左子节点 q->left = p->left; }else{ // 要删除的节点是其父节点的右子节点 q->right = p->left; } free(p); }else{ // 要删除的节点有左右子 Tree s = p->left, r = p; while(s->right != NULL){ r = s; s = s->right; } p->data = s->data; if(r == p){ // 要删除的节点的左子没有右子 r->left = s->left; }else{ // 要删除的节点的左子有右子 r->right = s->left; } free(s); } return t; } int main(){ Tree t = NULL; createTree(&t); // 创建二叉树 printf("先序遍历:"); preOrder(t); // 先序遍历 printf("\n中序遍历:"); inOrder(t); // 中序遍历 printf("\n后序遍历:"); postOrder(t); // 后序遍历 printf("\n"); int data; printf("请输入要插入的节点值:"); scanf("%d", &data); insert(t, data); // 插入节点 printf("中序遍历:"); inOrder(t); // 中序遍历 printf("\n请输入要查找的节点值:"); scanf("%d", &data); Tree node = search(t, data); // 查找节点 if(node != NULL){ printf("找到了节点:%d\n", node->data); }else{ printf("没有找到节点:%d\n", data); } printf("请输入要删除的节点值:"); scanf("%d", &data); t = delete(t, data); // 删除节点 printf("中序遍历:"); inOrder(t); // 中序遍历 return 0; } ``` 以上代码实现了创建二叉树、先序遍历、中序遍历、后序遍历、插入节点、查找节点、删除节点等操作。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值