二叉树的基本操作

  • 首先我们来了解一下什么是二叉树
    二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

  • 二叉树的特点:
    1.每个节点最多有两棵子树,即二叉树不存在度大于2的节点
    2.二叉树的子树有左右之分,其子树的顺序不能颠倒
    3.满二叉树: 在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子节点都在同一层上
    4.完全二叉树:如果一棵具有N个节点的二叉树的结构与满二叉树的前N个节点的结构相同,称为完全二叉树
    5.满二叉树与完全二叉树之间的关系:满二叉树是一个特殊的完全二叉树
    这里写图片描述

  • 二叉树的性质:
    1.若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)(i > 0)个节点;
    3.对任何一棵二叉树,如果其叶子节点个数为n0,度为2的非叶子节点个数为n2,则有n0 = n2 +1;
    4.具有n个节点的完全二叉树的深度为k为log2(n+1)上取整;
    5.对于具有n个节点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的节点有:
    (1)若 i>0,双亲序号:(i-1)/2 i=0,
    i为根节点编号,无双亲节点
    (2)若 n>2i+1,左孩子序号为2i+1,否则无左孩子
    (3)若 n>2i+1,右孩子序号为2i+1,否则无右孩子
    这里写图片描述

  • 二叉树的存储结构:
    二叉树主要有顺序存储结构和链式存储结构
    顺序存储结构:对于一棵完全二叉树所有节点按照层序自顶向下,同一层自左向右顺序编号,就得到一个节点的顺序序列
    优点:存储完全二叉树,简单省空间
    缺点:存储一般二叉树尤其单支树,存储空间利用不高
    链式存储结构:
    这里写图片描述

这里写图片描述

  • 二叉树的遍历:
    1.先序遍历:
    (1)访问根节点
    (2)遍历左子树
    (3)遍历右子树
    2.中序遍历:
    (1)遍历左子树
    (2)访问根节点
    (3)遍历右子树
    3.后续遍历:
    (1)遍历左子树
    (2)遍历右子树
    (3)访问根节点
    4.层序遍历:
    按照二叉树的层序次序,同一层中按先左子树再右子树的次序遍历二叉树

  • 下面就是对二叉树的四种遍历代码的实现:
    这里写图片描述

  • 首先是 .h 文件

#pragma once
#include<stdio.h>
typedef char TreeNodeType;

//使用孩子表示法来表示一个树
typedef struct TreeNode
{
    TreeNodeType data;
    struct TreeNode* lchild;
    struct TreeNode* rchild;
}TreeNode;

//对于链表来说,使用链表的头节点的指针表示一个链表
//对于一个树来书,使用根节点的指针来表示一个树
void TreeInit(TreeNode** pRoot);

void TreePreOrder(TreeNode* root);//先序
void TreeInOrder(TreeNode* root);//中序
void TreePostOrder(TreeNode* root);//后序
void TreeLevelOrder(TreeNode* root);//层序
#include <stdio.h>
#include"bin_tree.h"
#include"seqqueue.h"//因为层序用到了队列,所以将前面的队列代码引用进来
#include<stdlib.h>
#include<stddef.h>

TreeNode* CreateTreeNode(TreeNodeType value)//创建一个新的节点
{
    TreeNode* new_node = (TreeNode*)malloc(sizeof(TreeNode));
    new_node->data = value;
    new_node->lchild = NULL;
    new_node->rchild = NULL;
    return new_node;
}
void DestroyTreeNode(TreeNode* node)
{
    free(node);
}
void TreeInit(TreeNode** pRoot)//初始化
{
    if(pRoot == NULL)
    {
        //非法输入
        return;
    }
    if(*pRoot == NULL)
    {
        //空树
        return;
    }
    *pRoot = NULL;
    return;
}
  • 先序遍历的实现:
    这里写图片描述
void TreePreOrder(TreeNode* root)
{
    if(root == NULL)
    {
        printf("#");
        return;
    }
    //先访问根结点,再左子树,再右子树
    printf("%c",root->data);
    TreePreOrder(root->lchild);
    TreePreOrder(root->rchild);
    return;
}
void TestPreOrder()
{
    TEST_HEADER;
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->lchild = f;
    TreePreOrder(a);
    return;
}

这里写图片描述

  • 中序遍历的实现:
    这里写图片描述
void TreeInOrder(TreeNode* root)
{
    if(root == NULL)
    {
        return;
    }
    //先遍历左子树,再遍历根节点,最后遍历右子树
    TreeInOrder(root->lchild);
    printf("%c",root->data);
    TreeInOrder(root->rchild);
    return;
}
void TestInOrder()
{
    TEST_HEADER;
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->lchild = f;
    TreeInOrder(a);
    return;
}

这里写图片描述

  • 后序遍历的实现:
    这里写图片描述
void TreePostOrder(TreeNode* root)
{
    if(root == NULL)
    {
        return;
    }
    //先遍历左子树,再遍历右子树,最后访问根结点
    TreePostOrder(root->lchild);
    TreePostOrder(root->rchild);
    printf("%c",root->data);
    return;
}
void TestPostOrder()
{
    TEST_HEADER;
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->lchild = f;
    TreePostOrder(a);
    printf("\n");
    return;
}

这里写图片描述

  • 层序遍历的实现:
    这里写图片描述
void TestLevelOrder()
{
    TEST_HEADER;
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->lchild = f;
    TreeLevelOrder(a);
    printf("\n");
    return;
}
void TreeLevelOrder(TreeNode* root)
{
    if(root == NULL)
    {
        return;
    }
    SeqQueue queue;
    SeqQueueInit(&queue);
    SeqQueuePush(&queue,root);
    while(1)
    {
        SeqQueueType front;
        int ret = SeqQueueFront(&queue,&front);
        if(ret == 0)
        {
            //如果取队列首元素失败,说明队列为空
            //如果队列为空,说明遍历已经结束
            break;
        }
        printf("%c",front->data);
        SeqQueuePop(&queue);
        if(front->lchild != NULL)
        {
            SeqQueuePush(&queue,front->lchild);
        }
        if(front->rchild != NULL)
        {
            SeqQueuePush(&queue,front->rchild);
        }
    }
    printf("\n");
    return;
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值