树?二叉树?二叉搜索树BST(二叉树)

 

树的定义:

 

 

树(Tree): n(n≥0)个结点构成的有限集合。

 

 

  • 当n=0时,称为空树;

 

  • 对于任一棵非空树(n> 0),它具备以下性质:
  • 树中有一个称为“根(Root)”的特殊结点,用 root 表示;
  • 其余结点可分为m(m>0)个互不相交的有限集T1,T2,... ,Tm,其中每个集合本身又是一棵树,称为原来树的“子树(SubTree)”

 

注意:

  • 子树之间不可以相交
  • 除了根结点外,每个结点有且仅有一个父结点;
  • 一棵N个结点的树有N-1条边。

 

 

树的术语:

 

 

1.结点的度(Degree):结点的子树个数.

 

 

2.树的度:树的所有结点中最大的度数. (树的度通常为结点的个数N-1)

 

 

3.叶结点(Leaf):度为0的结点. (也称为叶子结点)

 

 

4.父结点(Parent):有子树的结点是其子树的根结点的父结点

 

 

5.子结点(Child):若A结点是B结点的父结点,则称B结点是A结点的子结点;子结点也称孩子结点。

 

 

6.兄弟结点(Sibling):具有同一父结点的各结点彼此是兄弟结点。

 

 

7.路径和路径长度:从结点n1到nk的路径为一个结点序列n1 , n2,… , nk, ni是 ni+1的父结点。路径所包含边的个数为路径的长度。

 

 

8.结点的层次(Level):规定根结点在1层,其它任一结点的层数是其父结点的层数加1。

 

 

9.树的深度(Depth):树中所有结点中的最大层次是这棵树的深度。

 

 

什么是二叉树?

二叉树的定义

  • 二叉树可以为空, 也就是没有结点.

  • 若不为空,则它是由根结点和称为其左子树TL和右子树TR的两个不相交的二叉树组成。

二叉树的特性

  1. 一个二叉树第 i 层的最大结点数为:2^(i-1), i >= 1;
  2. 深度为k的二叉树有最大结点总数为: 2^k - 1, k >= 1;
  3. 对任何非空二叉树 T,若n0表示叶结点的个数、n2是度为2的非叶结点个数,那么两者满足关系n0 = n2 + 1。

 

特殊的二叉树

  • 完美二叉树(Perfect Binary Tree) , 也称为满二叉树(Full Binary Tree)

    • 在二叉树中, 除了最下一层的叶结点外, 每层节点都有2个子结点, 就构成了满二叉树.

     

  • 完全二叉树(Complete Binary Tree)

    • 除二叉树最后一层外, 其他各层的节点数都达到最大个数.

    • 且最后一层从左向右的叶结点连续存在, 只缺右侧若干节点.

    • 完美二叉树是特殊的完全二叉树.

 

二叉树的存储

  • 二叉树的存储常见的方式是链表.

  • 链表存储:

    • 二叉树最常见的方式还是使用链表存储.

    • 每个结点封装成一个Node, Node中包含存储的数据, 左结点的引用, 右结点的引用.

 

 

 二叉搜索时的实现

 

前序遍历,中序遍历,后序遍历、寻找最值、删除节点、搜索节点

 

     class Node {
            constructor(data) {
                this.left = null;
                this.data = data;
                this.right = null;
            }
        }
        class BST {
            constructor() {
                this.root = null;
            }

            // 1.插入
            insert(ele) {
                // 创建新节点
                let newnode = new Node(ele);
                // console.log(newnode);
                if (this.root == null) { // 空树
                    this.root = newnode
                } else {
                    this.insertNode(this.root, newnode)
                }
            }

            insertNode(root, newnode) {

                if (newnode.data < root.data) { // 放左边
                    if (root.left == null) {
                        root.left = newnode
                    } else {
                        this.insertNode(root.left, newnode)
                    }
                } else { //放右边
                    if (root.right == null) {
                        root.right = newnode
                    } else {
                        this.insertNode(root.right, newnode)
                    }
                }

            }


            // 2.前序遍历
            preOrderTraversal() {
                this.preOrderTraversalNode(this.root)
            }

            preOrderTraversalNode(root) {

                if (root != null) { // {left:node,data:11,right:node} != null
                    // 1.根
                    console.log(root.data); //11 7  15
                    // 2.前序遍历左子树
                    this.preOrderTraversalNode(root.left)
                    // 3.前序遍历右子树
                    this.preOrderTraversalNode(root.right)
                }
            }


            // 3.中序遍历
            inOrderTraversal() {
                this.inOrderTraversalNode(this.root)
            }

            inOrderTraversalNode(root) {
                if (root != null) {
                    // 1.中序遍历左子树
                    this.inOrderTraversalNode(root.left)
                    // 2.根
                    console.log(root.data);
                    // 3.中序遍历右子树
                    this.inOrderTraversalNode(root.right)
                }
            }

            // 4.后序遍历
            postOrderTraversal() {
                this.postOrderTraversalNode(this.root)
            }
            postOrderTraversalNode(root) {
                if (root != null) {
                    // 1.后序遍历左子树
                    this.postOrderTraversalNode(root.left)

                    // 2.后序遍历右子树
                    this.postOrderTraversalNode(root.right)
                    // 3.根
                    console.log(root.data);
                }
            }

            // 5.最值
            getMin() {
                if (this.root == null) {
                    return
                } else {
                    let current = this.root;

                    while (current.left != null) {
                        current = current.left
                    }

                    return current.data
                }
            }

            getMax() {
                if (this.root == null) {
                    return
                } else {
                    let current = this.root;

                    while (current.right != null) {
                        current = current.right
                    }

                    return current.data
                }
            }

            remove(ele) {
                if (this.root == null) return
                let current = this.root,
                    parent, isLeftChild;
                // 找到删除节点和父节点,判断是左子节点吗?
                while (ele != current.data) {
                    if (ele < current.data) {
                        //左边找
                        parent = current;
                        current = current.left;
                        isLeftChild = true;
                    } else {
                        parent = current;
                        current = current.right;
                        isLeftChild = false;
                    }
                }

                let delNode = current;
                // console.log(`当前删除的元素是${current.data},删除元素的父节点是${parent.data},是左孩子吗?${isLeftChild}`);
                // 1.删除叶结点   左右子树都为空
                if (delNode.left == null && delNode.right == null) {
                    if (delNode == this.root) {
                        this.root = null;
                    } else {
                        if (isLeftChild) {
                            //左孩子
                            parent.left = null;
                        } else {
                            parent.right = null;
                        }
                    }
                } else if (delNode.left != null && delNode.right == null) { //2.只有一个左子节点的节点
                    if (delNode == this.root) {
                        this.root = delNode.left
                    } else {
                        if (isLeftChild) {
                            parent.left = delNode.left
                        } else {
                            parent.right = delNode.left
                        }
                    }
                } else if (delNode.left == null && delNode.right != null) { //只有一个右子节点的节点
                    if (delNode == this.root) {
                        this.root = delNode.right
                    } else {
                        if (isLeftChild) {
                            parent.left = delNode.right
                        } else {
                            parent.right = delNode.right
                        }
                    }
                } else { //删除有两个子节点    
                    let houji = this.gethouji(delNode);//后继为右子树中的最小值
                    if (delNode == this.root) {
                        this.root = houji;
                    } else {
                        if (isLeftChild) {
                            parent.left = houji;
                        } else {
                            parent.right = houji;
                        }
                    }
                    houji.left = delNode.left;
                }
            }

            gethouji(delNode) {
                let current = delNode.right; //后继
                let houjiparent = delNode;
                while (current.left != null) {
                    houjiparent = current;
                    current = current.left;
                }
                if (current != delNode.right) { //当后继为删除节点的右节点
                    houjiparent.left = current.right;
                    current.right = delNode.right
                }

                return current

            }

            seacrh(ele) {

                if (this.root == null) return

                let current = this.root;
                while (current) {
                    if (ele < current.data) {
                        //左边找
                        current = current.left
                    } else if (ele > current.data) {
                        current = current.right;
                    } else {
                        return true
                    }
                }

                return false
            }

        }

        let bst = new BST();
        bst.insert(11)
        bst.insert(7)
        bst.insert(15)
        bst.insert(5)
        bst.insert(3)
        bst.insert(9)
        bst.insert(8)
        bst.insert(10)
        bst.insert(13)
        bst.insert(12)
        bst.insert(14)
        bst.insert(20)
        bst.insert(18)
        bst.insert(25)
        bst.insert(19)

        console.log(bst.seacrh(9));
        console.log(bst.seacrh(100));

        console.log(bst);

 

posted on 2022-08-25 22:57  香香鲲  阅读(37)  评论(0编辑  收藏  举报