数据结构—树

数据结构—树

树的定义

树:n(n>=0)个节点构成的有限集合。当n=0时称为空树。
对于任一个非空树(n>0),它具备以下性质。
(1)有且仅有一个特定的称为根(root)的结点;
(2)其余结点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每一个集合本身又是一棵树,并称为根的子树(SubTree)

(a)树T

(b)子树T1

(c)子树T2

(d)子树T3

(e)子树T4

树的一些基本术语

01 节点的度:节点的子树个数

例如 树T 的根节点(即A节点)的度为4;

B节点的度为2;

C节点的度为1;

D节点的度为3;

E节点的度为0;

02树的度:树的节点中最大的度数

树T的度为4;

03叶节点:度为0的节点

比如树T 的F,L,H,M,J,K,E都是页节点。

04父节点:有子树的节点是其子树的根节点的父节点

比如A节点是子树T1 的根节点B的父节点。

05子节点:若A节点是B节点的父节点,则称B节点是A节点的子节点,子节点也称为孩子节点

比如B节点是A节点的子节点

06兄弟节点:具有同一父节点的各节点彼此是兄弟节点

比如B,C,D,E彼此是兄弟节点

07路径和路径长度:从节点N1到Nk的路径为一个节点序列N1,N2,...,NK,Ni是Ni+1的父节点。路径所包含的个数为路径的长度。

比如从A节点到L节点的路径的长度为4

08祖先节点:沿树根到某一节点路径上的所有节点都是这个节点的祖先节点

比如A节点到L节点的路径上A,B,G都是L节点的祖先节点

09子孙节点:某一节点的子树中的所有节点是这个节点的子孙

比如A节点的子树T1的所有节点B,F,G,L都是A节点的子孙

10节点的层次:规定根节点在第一层,其他任一节点的层数是其父节点的层数加1

比如B节点的层次是2,F节点的层次是3,L节点的层次是4

11树的深度:树中所有节点中的最大层次是这个树的深度

树T的深度为4

二叉树

二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

由二叉树定义以及图示分析得出二叉树有以下特点

01.每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点

02.如果有两个子结点,则其中一个子结点的值必须小于父结点,另一个子结点的值必须大于父结点

03.在二叉树的第i层上最多有2i-1 个节点 。(i>=1)

04.二叉树中如果深度为k,那么最多有2k-1个节点。

下面是使用java语言实现二叉查找树

/**
 * @author wwd
 * @title: BinaryTree
 * @description: 二叉树
 * @date 2022/3/299:04
 */
public class BinaryTree<Key extends Comparable<Key>,Value> {
    /**
    * 根节点
    **/
private Node root;

/**
 * 节点数量
 **/
private int n;

private class Node{
    /**
     * 节点键
     **/
    public Key key;
    /**
     * 节点值
     **/
    private Value value;

    /**
     * 左子节点
     **/
    public Node left;
    /**
     * 右子节点
     **/
    public Node right;
    /**
     * 父节点
     **/
    public Node parent;

    public Node(Key key, Value value,
     Node left, Node right,Node parent) {
        this.key = key;
        this.value = value;
        this.left = left;
        this.right = right;
        this.parent = parent;
    }
}


 public int size(){
    return n;
 }

 public void put(Key key,Value value){
    root=put(root,key,value,root);
 }

 private Node put(Node x,Key key,Value value,Node parent){
     if (x == null){
         //空树
         Node node = new Node(key,value,null,null,parent);
         n++;
         return node;
     }
     int compare = key.compareTo(x.key);
     if (compare>0){
         x.right = put(x.right, key, value,x);
     }else if (compare<0){
        x.left = put(x.left, key, value,x);
     }
     return x;
    }

    public Value get(Key key){
        return get(root,key);
    }
    private Value get(Node node,Key key){
        if (node == null){
            return null;
        }
        int compare = key.compareTo(node.key);
        if (compare>0){
           return get(node.right,key);
        }else if (compare<0){
            return get(node.left,key);
        }
        return node.value;
    }

    public void delete(Key key){
        delete(root,key);
    }

private void delete(Node node,Key key){
  if (null == node){
     //如果父节点为空直接返回
      return;
  }
  //查找到需要删除的节点
  int compare = key.compareTo(node.key);
  if (compare>0){
      //如果要删除的节点大于当前节点
      // 就去当前节点的右子节点递归查找
      delete(node.right,key);
  }else  if (compare<0){
      //如果要删除的节点小于当前节点
      // 就去当前节点的左子节点递归查找
      delete(node.left,key);
  }else{
      //找到需要删除的节点
      n--;
      Node p = node.parent;
      //情况1:没有子节点
      if (node.left==null && node.right == null){
          //没有子节点
          if (root == node){
              //如果删除的节点是根节点
              root = null;
          }else {
              //删除的不是根节点

              if (p.left==node){
                  //删除的是父节点的左节点
                  p.left = null;
              }else{
                  p.right = null;
              }
          }
      }else if (node.right == null){
          //情况2:删除的节点只有左节点
          Node ln = node.left;
          //删除的节点为根节点,将删除节点的左节点设置成根节点
          if (p==null){
              ln.parent = null;
              root = ln;
          }else{
              //非根节点
              if (node == p.left){
                  p.left = ln;
              }else{
                  p.right = ln;
              }
          }
      }else if (node.left == null){
            //情况2:删除的节点只有右节点
          Node lr = node.right;
          if (p==null){
              lr.parent = null;
              root = lr;
          }else{
              if (node== p.left){
                  p.left = lr;
              }else{
                  p.right = lr;
              }
          }
      }else {
          //有两个节点,找到后继节点,将值赋给删除节点,然后将后继节点删除掉即可
          //寻找
          Node successor = successor(node);//获取到后继节点
          node.value = successor.value;
          //后继节点为右子节点
          if (node.right == successor){
              //右子节点有右子节点
              if (successor.right != null) {
                  node.right = successor.right;
                  successor.right.parent = node;
              }else {//右子节点没有子节点
                  node.right = null;
              }
          }else {//后继节点必定是左节点
              successor.parent.left = null;
          }
      }

  }

    }

    /**
     * 查找后继节点
     * @param node 删除节点
     * @return 后继节点
     */
    private Node successor(Node node) {
        Node r = node.right;//r节点必定不为空
        while (r.left != null){
            r = r.left;
        }
        return r;
    }

    /**
     * 前序遍历
     * @param e 开始遍历元素
     */
    public void prevIterator(Node e){
        if (e != null) {
            System.out.print(e.key + " ");
            prevIterator(e.left);
            prevIterator(e.right);
        }
    }


    /**
     * 中序遍历
     * @param e
     */
    public void midIterator(Node e){
        if (e != null){
            midIterator(e.left);
            System.out.print(e.key + " ");
            midIterator(e.right);
        }
    }

    /**
     * 后续遍历
     * @param e 开始遍历元素
     */
    public void subIterator(Node e){
        if (e != null) {
            subIterator(e.left);
            subIterator(e.right);
            System.out.print(e.key + " ");
        }
    }

    public static void main(String[] args) {
        BinaryTree<String,String> binaryTree = new BinaryTree<>();
        binaryTree.put("18","哈哈18");
        binaryTree.put("16","哈哈16");
        binaryTree.put("17","哈哈15");
        binaryTree.put("30","哈哈30");
        binaryTree.put("32","哈哈32");
        binaryTree.put("10","哈哈10");
        binaryTree.put("25","哈哈25");
        binaryTree.midIterator(binaryTree.root);
        System.out.println();
        String o = binaryTree.get("30");
        System.out.println(o);
        binaryTree.delete("17");
        binaryTree.midIterator(binaryTree.root);
        System.out.println();
    }
}

下图是运行结果

如果对代码有疑问请留言交流哦

END

微信搜索 ”Java软件编程技术“ 关注我们获取更多软件开发技术

查看更多精彩内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值