Java数据结构之堆结构,基于泛型类中泛型数组的创建

首先创建Node类型作为堆的元素类型

class Node{
    public int nod;
    public int value;
    public Node(int nod, int value) {
        this.nod = nod;
        this.value = value;
    }
    
    public String toString() {
        return ""+value;
    }
}

堆结构的元素必须能够比较,定义Node类的比较器

class NodeComparator implements Comparator<Node>{
    @Override
    public int compare(Node o1, Node o2) {
        return o1.value - o2.value;
    }
}

首先明确,在Java里面要创建泛型数组需要借助import java.lang.reflect.Array;

创建类HeapExample1,其构造函数之一为:

    @SuppressWarnings("unchecked")
    public HeapExamples1(Class<T> type, boolean minheap, Comparator<T> cmpr) {
        this.minheap = minheap;
        this.heap = (T[]) Array.newInstance(type, DEFAULT_CAPACITY);
        this.cmpr = cmpr;
    }

  其中this.heap是T[]类型,创建泛型数组的方法是(T[]) Array.newInstance(type, DEFAULT_CAPACITY);

  其中type应为Node.class,DEFAULT_CAPACIT是数组长度。事实上这句话的意思就是this.heap = new T[DEFAULT_CAPACITY];然而这么做是会报错的,Java不允许通过new关键字创建泛型数组,具体原因可以百度。

  不过数组长度不代表数组的元素个数,数组长度是底层数组长度,如果不够需要扩容,而元素个数为private int heapLength;。和栈结构类同,除了确定长度的底层数组之外(如果不够再扩容),还定义了栈指针表示栈的高度,用于判断是否为空,或者是否溢出。

  堆结构的基本操作为插入,删除,返回元素个数,判断是否为空。还有自上而下调整和自下而上调整。插入和删除的过程中,通过调整操作来保证堆结构始终有序,事实上堆结构也是优先队列的基础。

堆结构的完整代码为:

public class HeapExamples1<T> {

    private boolean minheap;
    private T[] heap;
    private Comparator<T> cmpr;
    private int heapLength;
    
    private int DEFAULT_CAPACITY = 0x10; // 默认容量16
    
    @SuppressWarnings("unchecked")
    public HeapExamples1(Class<T> type, boolean minheap, Comparator<T> cmpr) {
        this.minheap = minheap;
        this.heap = (T[]) Array.newInstance(type, DEFAULT_CAPACITY);
        this.cmpr = cmpr;
    }

    public HeapExamples1(Class<T> type, boolean minheap) {
        this(type, minheap, null);
    }

    public HeapExamples1(Class<T> type) {
        this(type, true, null);
    }

    public HeapExamples1(Class<T> type, boolean minheap, T[]values, Comparator<T> cmpr) {
        this(type, minheap, cmpr);
        for (int i = 0; i < values.length; i++)
        {
            this.insert(values[i]);
//            this.printHeap();
        }
    }
    
    public boolean isEmpty() {
        return this.heapLength == 0;
    }
    public int size() {
        return this.heapLength;
    }
    public void printHeap(){
        for (int i = 0; i < heapLength; i++) {
            System.out.print(heap[i].toString()+", ");
        }
        System.out.println("\n");
    }
    
    public void insert(T x) {
        this.heap[this.heapLength++] = x;
        for (int i = this.heapLength/2-1;i>0; i = (i-1)/2)
            shif(i);
        shif(0);
    }
    
    @SuppressWarnings("unchecked")
    public void shif(int parent) {
        //Page289
        int end = this.size() - 1;
        int child = 2 * parent + 1;
        T value = this.heap[parent];
        while (child <= end) {
            int comp = 0;
            if (child < end) {
                T left = this.heap[child], right = this.heap[child+1];
                if (this.cmpr == null)
                    comp = ((Comparable<T>)left).compareTo(right);
                else
                    comp = this.cmpr.compare(left, right);
                if(this.minheap ? comp>0 : comp<0)
                    child++;
            }
            if (this.cmpr==null)
                comp = ((Comparable<T>)value).compareTo(this.heap[child]);
            else
                comp = this.cmpr.compare(value, this.heap[child]); 
            if (this.minheap ? comp>0 : comp<0) {
                this.heap[parent] = this.heap[child];
                parent = child;
                child = 2*parent+1;
            }else {
                break;
            }
        }
        this.heap[parent] = value;
    }
    
    public T removeRoot() {
        //Page290
        if (this.isEmpty())
            return null;
        T x = (T)this.heap[0];
        this.heap[0] = this.heap[this.heapLength-1];
        
        this.heap[this.heapLength-1] = null;
        this.heapLength--;
        
        if(this.heapLength>1)
            shif(0);
        return x;
    }

    public static void main(String[] args) {
        Node[] nodes = {new Node(0, 3),new Node(1,44),new Node(2,38),new Node(4,47),new Node(5,15),
                new Node(6,36), new Node(8,27), new Node(7,26),new Node(9,2)};
        System.out.println("大顶堆");
        HeapExamples1<Node> pq = new HeapExamples1<Node>(Node.class, true, nodes, new NodeComparator());
        System.out.println("堆的内容:");
        pq.printHeap();
        System.out.println("按顺序输出:");
        while (!pq.isEmpty()) {
            Node temp = pq.removeRoot();
            System.out.println("(value:"+temp.value+", nod:"+temp.nod+")");
        }
        
    }
}

结果:

大顶堆
堆的内容:
2, 3, 27, 15, 44, 38, 36, 47, 26,

按顺序输出:
(value:2, 9)
(value:3, 0)
(value:15, 5)
(value:26, 7)
(value:27, 8)
(value:36, 6)
(value:38, 2)
(value:44, 1)
(value:47, 4)

 

posted @ 2021-03-12 09:30  倦鸟已归时  阅读(274)  评论(0编辑  收藏  举报