[java] 堆,通过树节点的实现方式

堆是一种排序较为高效的数据结构,一般而言,对规模为n的数据进行排序可以将时间复杂度优化到O(nlogk)。java中已经对堆有实现好的官方库:优先队列(PriorityQueue)。一般而言的堆有两种实现方式:数组和树节点实现,目前网上基于数组的实现方式较多,树节点相较而言需要考虑较多的越界和空指针情况,比较繁琐,这里提供一种较为完善的实现。

通过new关键字新建堆后,可以通过调用build方法输入一个Node节点的数组批量初始化,也可以不调用,通过不断调用insert方法单个插入值。

文章提供的是小根堆,相较而言,将其转换成大根堆也并不复杂。

class Tree{
    public Node root;
    public int count = 1;

    public void build(Node[] build) {
        int length = build.length;
        root = build[0];
        if(length > 1) {
            for(int i = 1; i < length; i++) {
                if(i%2 == 1) {
                    build[i].parent = build[(i-1)/2];
                    build[(i-1)/2].left = build[i];
                }
                else {
                    build[i].parent = build[(i-1)/2];
                    build[(i-1)/2].right = build[i];
                }
                Node save = build[i];
                while(save.parent != null && save.data <= save.parent.data) {
                    int tempsave = save.data;
                    save.data = save.parent.data;
                    save.parent.data = tempsave;
                    save = save.parent;
                }
            }
        }
        count += length-1;
    }

    public void insert(int data) {
        Node add = new Node(data);
        if(root == null) {
            root = add;
        }
        else {
            count ++ ;
            StringBuilder binary = new StringBuilder();
            binary = Binary(count,binary);
            String temp = binary.toString();
            char[] order = temp.toCharArray();
            int length = order.length;
            Node current = root;
            for(int k = 1; k < length-1; k++) {
                if(order[k] == '0') {
                    current = current.left;
                }
                else if(order[k] == '1') {
                    current = current.right;
                }
            }
            if(order[length-1] == '0') {
                current.left = add;
                add.parent = current;
            }
            else if(order[length-1] == '1') {
                current.right = add;
                add.parent = current;
            }
            Node save = add;
            while(save.parent != null && save.data <= save.parent.data) {
                int tempsave = save.data;
                save.data = save.parent.data;
                save.parent.data = tempsave;
                save = save.parent;
            }
        }
    }

    public void delete() {
        StringBuilder binary = new StringBuilder();
        binary = Binary(count, binary);
        String temp = binary.toString();
        char[] order = temp.toCharArray();
        int length = order.length;
        Node current = root;
        for(int k = 1; k < length; k++) {
            if(order[k] == '0') {
                current = current.left;
            }
            else if(order[k] == '1') {
                current = current.right;
            }
        }
        int thisdata = current.data;
        if(length == 1) {
            count -- ;
            root = null;
            return;
        }
        else if(length == 2) {
            if(order[length-1] == '0') {
                root.left = null;
            }
            else if(order[length-1] == '1') {
                root.right = null;
            }
        }
        else {
            if(order[length-1] == '0') {
                current = current.parent;
                current.left = null;
            }
            else if(order[length-1] == '1') {
                current = current.parent;
                current.right = null;
            }
        }
        Node templeft = root.left;
        Node tempright = root.right;
        root = new Node(thisdata);
        root.left = templeft;
        root.right = tempright;
        if(templeft != null) {
            templeft.parent = root;
        }
        if(tempright != null) {
            tempright.parent = root;
        }
        Node find = root;
        while(find.left != null && find.right != null) {
            if(find.data <= find.left.data && find.data <= find.right.data) {
                break;
            }
            else if(find.data > find.left.data && find.data <= find.right.data) {
                int tempsave = find.data;
                find.data = find.left.data;
                find.left.data = tempsave;
                find = find.left;
            }
            else if(find.data <= find.left.data) {
                int tempsave = find.data;
                find.data = find.right.data;
                find.right.data = tempsave;
                find = find.right;
            }
            else {
                int tempsave = find.data;
                if(find.left.data < find.right.data) {
                    find.data = find.left.data;
                    find.left.data = tempsave;
                    find = find.left;
                }
                else {
                    find.data = find.right.data;
                    find.right.data = tempsave;
                    find = find.right;
                }
            }
        }
        if(find.left != null) {
            if(find.data > find.left.data) {
                int tempsave = find.data;
                find.data = find.left.data;
                find.left.data = tempsave;
            }
        }
        count --;
    }

    public void query() {
        System.out.println(root.data);
    }

    public static StringBuilder Binary(int value, StringBuilder binary) {
        if(value > 0) {
            int n = value % 2;
            value /= 2;
            binary.insert(0, n);
            Binary(value, binary);
        }
        return binary;
    }
}

class Node{
    public int data;
    public Node left = null;
    public Node right = null;
    public Node parent = null;

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

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Java实现哈夫曼(Huffman Tree),也称为最优二叉或霍夫曼编码,通常用于数据压缩算法。这里是一个简单的步骤和代码示例: 1. **构建频率表**:首先,收集并统计每个字符在输入序列中的出现频率。 2. **创建节点**:创建一个节点类,包含字符、频率和左右子节点。 ```java class Node { char data; int frequency; Node left, right; // 构造方法和 getters/setters... } ``` 3. **构造初始集合**:将所有字符及其频率放入一个优先队列(最小)。 4. **构建哈夫曼**: - 取出队列中的两个频率最低的节点,合并成一个新的节点,新节点的频率为两个节点之和,左子节点为第一个节点,右子节点为第二个节点。 - 将新节点放回优先队列。 - 重复此过程,直到队列只剩下一个节点,即为哈夫曼的根节点。 5. **编码过程**:从根节点开始,遍历的过程形成编码规则。如果向左走代表0,向右走代表1。 6. **代码实现**: ```java import java.util.PriorityQueue; public class HuffmanTree { private static PriorityQueue<Node> heap = new PriorityQueue<>((a, b) -> a.frequency - b.frequency); //... 其他方法 public static String compress(char[] input) { // 建立频率表并放入 for (char ch : input) { incrementFrequency(ch); } buildHuffmanTree(); // 编码 StringBuilder encoded = new StringBuilder(); buildCode(encoded, root, ""); return encoded.toString(); } private static void buildHuffmanTree() { // 代码省略... } // ...其他方法 } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值