算法学习之二叉树

概念

每个节点最多有两个的子节点的树,称为二叉树,二叉树是最基础的树,其他的算法树大多是在二叉树的前提下加以限制,或有特殊要求。

二叉树的相关术语:

  • 节点:包含一个数据元素及若干指向子树分支的信息,一般一个节点所包含的属性有:节点数值,左节点,右节点

  • 节点的度:一个节点拥有子树的数目称为节点的度,即一个节点有几个子分支,没有子节点度为0,仅有一个子节点度为1,以此类推

  • 叶子节点:也称为终端节点,没有子树的节点或者度为零的节点

  • 分支节点:也称为非终端节点,度不为零的节点称为非终端节点

  • 树的度:树中所有节点的度的最大值

  • 节点的层次:从根节点开始,假设根节点为第1层,根节点的子节点为第2层,依此类推,如果某一个节点位于第L层,则其子节点位于第L+1层

  • 树的深度:也称为树的高度,树中所有节点的层次最大值称为树的深度

  • 有序树:如果树中各棵子树的次序是有先后次序,则称该树为有序树

  • 无序树:如果树中各棵子树的次序没有先后次序,则称该树为无序树

  • 森林:由m(m≥0)棵互不相交的树构成一片森林。如果把一棵非空的树的根节点删除,则该树就变成了一片森林,森林中的树由原来根节点的各棵子树构成

二叉树的性质

  • n0 + n2 = n

  • n0 = n2 + 1

  • 2* n2 + 1 = n

  • n2 = (n-1)/2

数字为节点的度

二叉树的创建

在java中创建一个二叉树分为两部分:节点和树

这里直接上代码

/**节点类**/
class TreeNode {
    private int id;
    private String name;
    private TreeNode left;
    private TreeNode right;

    @Override
    public String toString() {
        return "TreeNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public TreeNode(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public TreeNode() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}

/**树类**/
class BinaryTree{
    private TreeNode root;

    public void setRoot(TreeNode root) {
        this.root = root;
    }
}

 有了这两个类,我们只需创建几个节点,将其中一个节点设置为树的根结点,并将其余的节点放在其左右节点即可

public class BinaryTreeDemo {
    public static void main(String[] args) {
        // 先创建二叉树的节点
        BinaryTree binaryTree = new BinaryTree();
        TreeNode root = new TreeNode(1,"嘉然");
        TreeNode node2 = new TreeNode(2,"向晚");
        TreeNode node3 = new TreeNode(3,"乃琳");
        TreeNode node4 = new TreeNode(4,"贝拉");
        TreeNode node5 = new TreeNode(5,"珈乐");

        // 手动创建二叉树
        binaryTree.setRoot(root);
        root.setLeft(node3);
        root.setRight(node2);
        node2.setRight(node4);
        node2.setLeft(node5);
    }
}

此时我们就创建好了一个二叉树,如图

二叉树的遍历

二叉树的遍历有三种:先序遍历,中序遍历,后序遍历

  • 先序遍历

    • 遍历顺序为根、左、右,即先遍历一个树的根结点,在遍历其左子树,最后是右子树,遍历是一个递归的过程,直到遍历到没有左右子节点的叶子节点返回上一层

    • 先序遍历输出上述二叉树的结果为:1、3、2、5、4

  • 中序遍历

    • 遍历顺序为左、根、右,即先遍历一个树的左子树,在遍历其根结点,最后是右子树,遍历是一个递归的过程,直到遍历到没有左右子节点的叶子节点返回上一层

    • 中序遍历输出上述二叉树的结果为:3、1、5、2、4

  • 后序遍历

    • 遍历顺序为左、右、根,即先遍历一个树的左子树,在遍历其右子树,最后是根结点,遍历是一个递归的过程,直到遍历到没有左右子节点的叶子节点返回上一层

    • 中序遍历输出上述二叉树的结果为:3、5、4、2、1

这里给出三种遍历打印和查找的代码

class TreeNode {

    // 先序遍历(根 左 右)
    public void preOrder() {
        System.out.println(this);
        if (this.left != null) {
            this.left.preOrder();
        }
        if (this.right != null) {
            this.right.preOrder();
        }
    }

    // 中序遍历(左 根 右)
    public void infixOrder() {
        if (this.left != null) {
            this.left.infixOrder();
        }
        System.out.println(this);
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

    // 后序遍历(左 右 根)
    public void postOrder() {

        if (this.left != null) {
            this.left.postOrder();
        }
        if (this.right != null) {
            this.right.postOrder();
        }
        System.out.println(this);
    }

    /**
     * 先序查找
     * @param id
     * @return
     */
    public TreeNode preFind(int id) {
        TreeNode treeNode = null;
        if (this.id == id) {
            treeNode = this;
            return treeNode;
        }
        if (this.left != null) {
            treeNode = this.left.preFind(id);
        }
        if (this.right != null) {
            treeNode = this.right.preFind(id);
        }
        return treeNode;
    }

    /**
     * 中序查找
     * @param id
     * @return
     */
    public TreeNode infixFind(int id) {
        TreeNode treeNode = null;
        if (this.left != null) {
            treeNode = this.left.infixFind(id);
        }
        if (this.id == id) {
            treeNode = this;
            return treeNode;
        }
        if (this.right != null) {
            treeNode = this.right.infixFind(id);
        }
        return treeNode;
    }

    /**
     * 后序查找
     * @param id
     * @return
     */
    public TreeNode postFind(int id) {
        TreeNode treeNode = null;
        if (this.left != null) {
            treeNode = this.left.postFind(id);
        }
        if (this.right != null) {
            treeNode = this.right.postFind(id);
        }

        if (this.id == id) {
            treeNode = this;
            return treeNode;
        }
        return treeNode;
    }
}

class BinaryTree{
    /**
     * 先序查找
     * @param id
     * @return
     */
    public TreeNode preFind(int id){
        if (this.root == null){
            System.out.println("二叉树为空");
            return null;
        }else {
            return root.preFind(id);
        }
    }

    /**
     * 中需查找
     * @param id
     * @return
     */
    public TreeNode infixFind(int id){
        if (this.root == null){
            System.out.println("二叉树为空");
            return null;
        }else {
            return root.infixFind(id);
        }
    }

    /**
     * 后序查找
     * @param id
     * @return
     */
    public TreeNode postFind(int id){
        if (this.root == null){
            System.out.println("二叉树为空");
            return null;
        }else {
            return root.postFind(id);
        }
    }

    // 先序遍历
    public void preOrder(){
        if (this.root != null) {
            root.preOrder();
        }else {
            System.out.println("二叉树为空,无法遍历");
        }
    }

    // 中序遍历
    public void infixOrder(){
        if (this.root != null){
            root.infixOrder();
        }else {
            System.out.println("二叉树为空,无法遍历");
        }
    }

    // 后序遍历
    public void postOrder(){
        if (this.root != null){
            root.postOrder();
        }else {
            System.out.println("二叉树为空,无法遍历");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我可以用中文回答你关于使用C语言的问题。 C语言是一种通用的高级编程语言,广泛应用于各种领域,包括系统编程、嵌入式系统、游戏开发、科学计算等。它是一种编译型语言,可以通过编译器将代码转换成计算机可以执行的二进制代码。 使用C语言编写程序需要一定的编程知识和技能。如果您是初学者,可以通过学习基本的语法、变量、运算符、流程控制语句等内容来入门。此外,还可以学习C标准库中的函数,例如字符串处理、输入输出、内存分配等。 在使用C语言时,还需要注意内存管理和指针的使用。C语言中的指针可以用来访问和操作内存中的数据,但需要注意指针的指向和内存释放等问题,否则可能会导致程序崩溃或安全漏洞。 总之,学习和使用C语言需要一定的时间和精力,但掌握了它可以让您编写高效、可靠的程序,并在计算机编程领域中获得更多的机会和发展。 ### 回答2: C语言是一种高级程序设计语言,广泛用于软件开发和系统编程。它于1972年由丹尼斯·里奇和肯·汤普逊在贝尔实验室开发。C语言的设计目标是提供一种简洁、高效和可移植的编程语言,以方便开发人员编写高质量的代码。 C语言具有许多优势。首先,它具有结构化编程和模块化编程的特性,使得代码易于理解和维护。其次,C语言的语法相对简洁,学习起来相对容易。因此,它被广泛用于教育和初学者编程课程中。另外,C语言的执行效率非常高,代码能够直接翻译为机器语言,因此在嵌入式系统和高性能计算领域得到广泛应用。 C语言在软件开发和系统编程中有很多应用。它是编写操作系统、嵌入式系统和驱动程序的首选语言。C语言还被用于开发各种应用程序,包括网络应用、数据库、图形界面、游戏等。此外,C语言也用于编写算法和解决复杂问题,如图形处理、人工智能、机器学习等。 C语言的标准库提供了许多函数和数据结构,大大简化了编程过程。此外,C语言还支持指针操作,使得开发人员能够直接访问内存地址,进一步提升了程序的灵活性和效率。 总之,C语言是一种强大而灵活的编程语言,被广泛应用于软件开发和系统编程。它的简洁语法、高效执行和广泛应用使其成为学习和使用的理想选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值