数据结构:树

1.二叉树概念
二叉树:任何一个节点的子节点不超过2

满二叉树:节点总数为:2∧n-1 (n是树的高度)
在这里插入图片描述

完全二叉树:如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。

在这里插入图片描述
2.二叉树的遍历
二叉树节点:

class Node{
    private Node leftNode;
    private Node rightNode;
    private int value;

    public Node(int value) {
        this.value = value;
    }

    public Node getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(int n) {
        this.leftNode = new Node(n);
    }

    public Node getRightNode() {
        return rightNode;
    }

    public void setRightNode(int n) {
        this.rightNode =  new Node(n);
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

前序遍历:

public void Preorder() {
    System.out.println(this.getValue());
    if(this.leftNode!=null){
        this.leftNode.Preorder();
    }
    if(this.rightNode!=null){
        this.rightNode.Preorder();
    }
}

中序遍历:

public void Middle_order(){
    if(this.leftNode!=null){
        this.leftNode.Middle_order();
    }
    System.out.println(this.getValue());
    if(this.rightNode!=null){
        this.rightNode.Middle_order();
    }

}

后序遍历:

public void Post_order(){
    if(this.leftNode!=null){
        this.leftNode.Post_order();
    }
  
    if(this.rightNode!=null){
        this.rightNode.Post_order();
    }
    
    System.out.println(this.getValue());
}

前序查找:(省略中序查找与后序查找)

public Node search(int i) {
   if(this.value==i){return this;}
    Node result=null;
   if(this.leftNode!=null){
       result=leftNode.search(i);
   }
   if(result!=null){return result;}
    if(this.rightNode!=null){
        result=rightNode.search(i);
    }
    return result;
}

3.顺序存储二叉树
顺序二叉树特点:
(1)顺序二叉树只考虑完全二叉树
(2)第n个元素的左子节点为 2n+1
(3)第n个元素的右子节点为 2
n+2
(4)第n个元素的父节点为(n-1)/2
n从0开始编号

✏遍历顺序存储的二叉树:

/*顺序存储二叉树*/
public class ArrBinarytreeDemo {
    public static void main(String[] args) {
        int[] arr=new int[]{1,2,3,4,5,6,7};
        ArrBinarytree a=new ArrBinarytree(arr);
        a.Preorder();
    }
}

class ArrBinarytree{
    private int[] arr;
    public ArrBinarytree(int[] arr){
        this.arr=arr;
    }
    public void Preorder(){
        this.Preorder(0);
    }
    public void Preorder(int index) {
        if(arr==null||arr.length<0){
            System.out.println("数组为空,无法遍历");
            return;
        }
        System.out.println(arr[index]);

        if((index*2+1)<arr.length){
            Preorder(2*index+1);
        }
        if((index*2+2)<arr.length){
            Preorder(2*index+2);
        }
    }

}

4.线索二叉树
线索二叉树节点类:

class Node {
    private Node leftNode;
    private Node rightNode;
    private int value;
    //Leftflag=0 时LeftNode指向左儿子;Leftflag=1 时LeftNode指向前驱节点。
    public int Leftflag = 0;
    //Rightflag=0 时RightNode指向左儿子;Rightflag=1 时RightNode指向前驱节点。
    public int Rightflag =0;

    public Node(int value) {
        this.value = value;
    }

    public Node getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(Node node) {
        this.leftNode = node;
    }

    public Node getRightNode() {
        return rightNode;
    }

    public void setRightNode(Node node) {
        this.rightNode = node;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

}
class ThreadedBinaryTree{
     Node pre=null;  // 存储当前当前节点的父节点
public static void ThreadNode(Node node){//中序线索化二叉树
       if(node==null){return;}
      //递归左子节点
      ThreadNode(node.getLeftNode());
      if(node.getLeftNode()==null){
            node.setLeftNode(pre);
            node.Leftflag=1;
      }
      if(pre!=null&&pre.getRightNode()==null){
          pre.setRightNode(node);
          pre.Rightflag=1;
      }
        pre=node;
      //递归右子节点
      ThreadNode(node.getRightNode());
    }
}

遍历线索二叉树:

public static void threadIterate(Node node){//输入树的根节点进行遍历
    //打印输出,直到节点都遍历完
    while(node!=null){
        while(node.Leftflag!=1){
            //找到左下角的首节点
            node=node.getLeftNode();
        }
        //打印当前节点
        System.out.println(node.getValue());
        while (node.Rightflag==1){
            node=node.getRightNode();
            System.out.println(node.getValue());
        }
            node=node.getRightNode();
    }
}

哈夫曼树:
叶子节点的带权路径:叶子节点的权值*(叶子节点与根节点的路径长度)
WPL:所有叶子节点的带权路径之和

🦁贪心法构造哈夫曼树:
1.对于数组[3,7,8,29,5,11,23,14]
2.将数组内的所以元素变为一个叶子节点,用List存放
3.排序List,得到最小的两个节点
4.将取出的两个节点连成一棵树,根节点的权值为两颗节点权值之和
5.删除取出的两个小节点,将合并后的根节点存入List中
6.循环3~5步,直到List内只有唯一一个根节点,就是哈夫曼树

🖥代码实现
先定义一个树的节点类

public class Node implements Comparable<Node>{
    int value;
    Node left;
    Node right;
    public Node(int value){
        this.value=value;
    }

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

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

    @Override
    public int compareTo(Node o) {
        return this.value-o.value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }
}

实现哈夫曼树构建:

public class HaffmanTree {
    public static void main(String[] args) {
        int[] arr={3,7,8,29,5,11,23,14};
        Node HuffmanRoot=createHuffmanTree(arr);
        System.out.println(HuffmanRoot);
    }

    public static Node createHuffmanTree(int[] arr){
       //使用数组中的元素创建若干个只有一个节点的二叉树。
        List<Node> Nodes=new ArrayList<Node>();
        for(int value:arr){
            Nodes.add(new Node(value));
        }
       //循环处理,直到数组内只有一个节点为止
        while(Nodes.size()>1){
            //对树节点数组进行排序
            Collections.sort(Nodes);
            //取出两个最小的节点
            Node left=Nodes.get(Nodes.size()-1);
            Node right=Nodes.get(Nodes.size()-2);
            Node newNode=new Node(left.value+right.value);
            newNode.setLeft(left);
            newNode.setRight(right);
            Nodes.remove(left);
            Nodes.remove(right);
            Nodes.add(newNode);
        }
        return Nodes.get(0);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值