二叉树与二叉查找树的基本方法java实现

转载自:https://www.cnblogs.com/eudiwffe/p/6207196.html

https://blog.csdn.net/weixin_38629529/article/details/81171245

目录

1.二叉树(Binary Tree)

2.完全二叉树:

3.满二叉树:

4.二叉查找树

5.二叉查找树基本方法 

1)二叉查找树表示

2)查找一个元素

3) 插入一个元素

4)树的遍历(前序、中序、后序、深度遍历、广度遍历、递归与非递归)


1.二叉树(Binary Tree)

一个节点分出两个节点,称其为左右子节点;每个子节点又可以分出两个子节点,这样递归分叉,其形状很像一颗倒着的树。

二叉树限制了每个节点最多有两个子节点,没有子节点的节点称为叶子

二叉树引导出很多名词概念:

其中节点B只有一个子节点D;

叶子:D, E, F没有子节点,被称为叶子

深度: 指的是根节点到该节点的路径长度,A的深度为0,D的深度为2

高度:只有一个节点的树,高度为0,非空树的高度为从根结点到最远的叶结点的路径长度,习惯上将空树高度定义为-1。

出度:节点C分出两子节点,所以C的出度为2;

入度:C有且只有一个父节点,所以其入度为1。 

出度、入度的概念来源于图(Graph,一种更加高级复杂的数据结构),二叉树或者说树形数据结构也是一类特殊的图,

二叉树的根节点入度为0,叶子节点出度为0。

2.完全二叉树

除了最高层以外,其余层节点个数都达到最大值,并且最高层节点都优先集中在最左边

3.满二叉树

除了最高层有叶子节点,其余层无叶子,并且非叶子节点都有2个子节点。

满二叉树一定是一个完全二叉树,反之则不然

4.二叉查找树

二叉查找树(binary search tree,BST)是一种特殊的二叉树,相对较小的值保存在左节点中,较大的值保存在右节点中。

二叉查找树(没有重复元素)的特征是:对于树中的每一个结点,它的左子树中结点的值都小于该结点的值,而它的右子树中结点的值都大于该结点的值。

5.二叉查找树基本方法 

转载自:《Java语言程序设计进阶篇》

1)二叉查找树表示

使用一个链式结点的集合来表示二叉树。每个结点都包含一个数值和两个称为left和right的链接,分别指向左孩子和右孩子,如图所示

节点可以定义为一个类:E是泛型,表示该节点可以放不同的类型

class TreeNode<E> {
    protected E element;
    protected TreeNode left;
    protected TreeNode right;
    public TreeNode(E element) {
        this.element = element;
    }
}

创建一颗树:

 代码如下:

        TreeNode<Integer> root = new TreeNode<>(60);
        root.left = new TreeNode(50);
        root.right = new TreeNode(70);

变量root指向树的根结点。如果树为空,那root的值为null

2)查找一个元素

要在二叉查找树中查找一个元素,可从根结点开始向下扫描,直到找到一个匹配元素,或者达到一棵空子树为止。

该算法在程序清单1中描述。让current指向根结点,

重复下面的步骤直到current为null或者元素匹配current.element:

如果element小于current.element,就将current.left赋给current

如果element大于current.element,就将current.right赋给current

如果element等于current.element,就返回true

如果current为null,那么子树为空且该元素不在这棵树中 返回false

    public boolean search(E element){
        TreeNode<E> current = root;
        while(current!=null){
            if (element < current.element){
                current = current.left;
            }else if(element > current.element){
                current = current.right
            }else
            return true;
        
        }
        return false;
    }

3) 插入一个元素

为了在BST中插入一个元素,需要确定在树中插入元素的位置。关键思路是确定新结点的父结点所在的位置

若当前树不为空,寻找新元素结点的父结点位置。 如果新元素小于父元素值,设置为左子节点,大于则设置为右子节点。

4)树的遍历

树的遍历(tree traversal)就是访问树中每个结点一次且只有一次的过程。

中序(inorder)、前序(preorder)、后序(postorder)、深度优先(depth-first)和广度优先(breadth-first)等遍历方法。

A 中序遍历(inorder traversal)法

首先递归地访问当前结点的左子树,然后访问当前结点,最后递归地访问该结点的右子树。中序遍历法以递增顺序显示BST中的所有结点。

B 后序遍历(postorder traversal)法,首先递归地访问当前结点的左子树,然后递地访问该结点的右子树,最后访问该结点本身。后序遍历的一个应用就是找出一个文件系统中目录的个数。

C 前序遍历(preorder traversal)法,首先访问当前结点,然后递归地访问该结点的左子树,最后递归地访问该结点的右子树

D 深度优先遍历法与前序遍历法相同。

E 广度优先遍历法逐层访问树中的结点。首先访问根结点,然后从左往右访问根结点的所有子结点,再从左往右访问根结点的所有孙子结点,以此类推。

public class TreeNode {
    protected int data;
    protected TreeNode left;
    protected TreeNode right;
    public TreeNode(int data) {
        this.data = data;
    }

    /**递归 就是有调用自己————————————*/
    /**前序递归遍历*/
    public  static void preOrder(TreeNode root){
        if (root != null){
            System.out.print(root.data+"\t");
            preOrder(root.left);
            preOrder(root.right);
        }
    }

    /**中序递归遍历*/
    public static void inOrder(TreeNode root){
        if (root != null){
            inOrder(root.left);
            System.out.print(root.data+"\t");
            inOrder(root.right);
        }
    }
    /**后序递归遍历*/
    public static void postOrder(TreeNode root){
        if (root != null){
            postOrder(root.left);
            postOrder(root.right);
            System.out.print(root.data+"\t");
        }
    }
    /**非递归-----------非递归写法一定会用到栈-------------------*/
//    如何写非递归代码呢?
// 一句话:让代码跟着思维走。我们的思维是什么?思维就是中序遍历的路径。
//    首先,我们遍历左子树,边遍历边打印,并把根节点存入栈中,
//    以后需借助这些节点进入右子树开启新一轮的循环。
//    接下来就是:出栈,根据栈顶节点进入右子树。
    /**前序非递归遍历*/
    public static void preOrderNoRe(TreeNode root){
        Stack<TreeNode> s = new Stack<>();
        while (root != null || !s.empty()) {
            //边遍历 边打印 将根节点存入栈中
            while (root !=null){
                System.out.print(root.data+"\t");
                s.push(root);
                root = root.left;
            }
            if (!s.empty()){
                root = s.pop();
                root = root.right;
            }
        }

    }

    // 中序遍历非递归
    public static void inOrderNoRe(TreeNode root) {
        Stack<TreeNode> s = new Stack<TreeNode>();
        while (root != null || !s.empty()) {
            while (root != null) {
                s.push(root);
                root = root.left;
            }
            if (!s.empty()) {
                root = s.pop();
                System.out.print(root.data+"\t");
                root = root.right;
            }
        }
    }

    // 后序遍历非递归
    public static void postOrderNoRe(TreeNode root) {
        Stack<TreeNode> s = new Stack<TreeNode>();
        Stack<Integer> s2 = new Stack<Integer>();
        Integer i = new Integer(1);
        while (root != null || !s.empty()) {
            while (root != null) {
                s.push(root);
                s2.push(new Integer(0));
                root = root.left;
            }
            while (!s.empty() && s2.peek().equals(i)) {
                s2.pop();
                System.out.print(s.pop().data+"\t");
            }

            if (!s.empty()) {
                s2.pop();
                s2.push(new Integer(1));
                root = s.peek();
                root = root.right;
            }
        }
    }


}

5)删除BST中的一个元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值