堆排序算法Java面向对象实现

来源:互联网 发布:淘宝客营销案例 编辑:程序博客网 时间:2024/06/06 00:28

堆排序算法介绍

堆是一种重要的数据结构,为一棵完全二叉树, 底层如果用数组存储数据的话,假设某个元素为序号为i(Java数组从0开始,i为0到n-1),如果它有左子树,那么左子树的位置是2i+1,如果有右子树,右子树的位置是2i+2,如果有父节点,父节点的位置是(n-1)/2取整。分为最大堆和最小堆,最大堆的任意子树根节点不小于任意子结点,最小堆的根节点不大于任意子结点。所谓堆排序就是利用堆这种数据结构来对数组排序,我们使用的是最大堆。处理的思想和冒泡排序,选择排序非常的类似,一层层封顶,只是最大元素的选取使用了最大堆。最大堆的最大元素一定在第0位置,构建好堆之后,交换0位置元素与顶即可。堆排序为原位排序(空间小), 且最坏运行时间是O(nlgn),是渐进最优的比较排序算法。

实现思路

堆排序简单来说可以概括为三个步骤:
1.根据数据建立无序的堆
2.对堆按大顶堆或小顶堆调整。大顶堆即是满足树中根节点的值始终大于孩子节点的值,局部也满足这个条件,小顶堆相反。
3.每一次调整过后再顶部得到这些数据的最大值或最小值,出堆,并把最后一个节点放到顶部,以此循环,直到堆里的数据全部给出。

具体代码

堆排序类

public class HeapSort<T extends Comparable<T>> {    private List<T> sub;// 排序资源列表    private Integer listLength = 0;// 元素个数    private Integer nodeNum = 0;// 堆中节点个数    private Node top;// 顶节点    private Node end;// 最后一个节点    private Node end2;// 倒数第二个节点    private List<T> result = new ArrayList<T>();//排序结果    public HeapSort(List<T> srcList) {        this.nodeNum = 1;        this.top = new Node((T)srcList.get(0), 1, 1);// 顶节点默认层数为1,编号为1        this.sub = srcList.subList(1, srcList.size());        this.listLength = srcList.size();        this.end = null;        createHeap(this.top);    }    // 创建堆    private void createHeap(Node h) {        if (sub == null || sub.size() <= 0) {            return;        }        // 添加左孩子        createLeftChild(h);        // 添加右孩子        createRightChild(h);        return;    }    // 创建左孩子    private void createLeftChild(Node h) {        if (h.getLeft() != null) {            return;        }        if (listLength >= h.getNum().intValue() * 2) {// 可以有左孩子            nodeNum++;            Node leftChild = new Node((T)sub.get(0), h.getFloor() + 1, h.getNum() * 2);            h.setLeft(leftChild);            leftChild.setParent(h);            if (leftChild.getNum() == listLength) {// 最后一个节点                end = leftChild;            }            sub = sub.subList(1, sub.size());            createHeap(leftChild);        }else{            end = h;        }        return;    }    // 创建右孩子    private void createRightChild(Node h) {        if (h.getRight() != null) {            return;        }        if (listLength >= h.getNum().intValue() * 2 + 1) {// 可以有右孩子            nodeNum++;            Node rightChild = new Node((T)sub.get(0), h.getFloor() + 1, h.getNum() * 2 + 1);            h.setRight(rightChild);            rightChild.setParent(h);            if (rightChild.getNum() == listLength) {// 最后一个节点                end = rightChild;            }            sub = sub.subList(1, sub.size());            createHeap(rightChild);        }        return;    }    /**     * 调整大顶堆,并且返回最顶端的值     * @param h 根节点     * @return     */    private T adjustMaxHeap(Node h) {        // 通过迭代遍历根节点和孩子节点,调整为根节点最大        if (h == null) {            return null;        }        if(nodeNum==1){            return (T) top.getValue();        }        if (h.getNum().equals(nodeNum - 1)) {// 调整堆的时候添加上倒数第二个节点的引用,以便删除最后一个节点后将end指向此节点            end2 = h;        }        T top = (T) h.getValue();        // 调整左孩子        T maxLeft = adjustMaxHeap(h.getLeft());        // 调整右孩子        T maxRight = adjustMaxHeap(h.getRight());        if (maxLeft == null && maxRight == null) {// 没有左右孩子            return (T) h.getValue();        } else if (maxLeft == null && maxRight != null) {// 没有左孩子            if (maxRight.compareTo(top)>0) {                h.setValue(maxRight);                h.getRight().setValue(top);            }        } else if (maxLeft != null && maxRight == null) {// 没有右孩子            if (maxLeft.compareTo(top)>0) {                h.setValue(maxLeft);                h.getLeft().setValue(top);            }        } else {// 有左右孩子            if (maxLeft.compareTo(top)>0 || maxRight.compareTo(top)>0) {                if (maxLeft.compareTo(maxRight)>=0) {// 左孩子最大                    h.setValue(maxLeft);                    h.getLeft().setValue(top);                } else {// 右孩子最大                    h.setValue(maxRight);                    h.getRight().setValue(top);                }            }        }        return (T) h.getValue();    }    /**     * 堆排序方法(大顶堆)     * @param srcList     * @return     */    public List<T> sort() {        // 循环调整堆        while (floorMoreOne()) {            T max = adjustMaxHeap(top);            //stack.push(max);            result.add((T) max);            top.setValue(end.getValue());            Node parent = end.getParent();            if (end.getParent() == null) {                break;            }            if (parent.getLeft() != null && parent.getLeft().getNum().intValue() == end.getNum().intValue()) {                parent.setLeft(null);            }            if (parent.getRight() != null && parent.getRight().getNum().intValue() == end.getNum().intValue()) {                parent.setRight(null);            }            nodeNum--;            end = end2;            // end指向倒数第二个节点        }        result.add((T) top.getValue());        return result;    }    // 判断堆的层数是否大于一    private boolean floorMoreOne() {        if (top.getLeft() != null || top.getRight() != null) {            return true;        }        return false;    }}

节点类

public class Node<T> {    private T value;// 节点的值    private Integer floor;// 节点所在层    private Integer num;// 节点编号    private Node parent;// 父节点    private Node left;// 左孩子    private Node right;// 右孩子    public Node() {    }    public Node(T value) {        super();        this.value = value;    }    public Node(T value, Integer floor) {        super();        this.value = value;        this.floor = floor;    }    public Node(T value, Integer floor, Integer num) {        super();        this.value = value;        this.floor = floor;        this.num = num;    }    public Node<T> getLeft() {        return left;    }    public Integer getNum() {        return num;    }    public void setLeft(Node leftChild) {        this.left = leftChild;    }    public void setRight(Node rightChild) {        this.right = rightChild;    }    public void setParent(Node h) {        this.parent = h;    }    public int getFloor() {        return floor;    }    public T getValue() {        return value;    }    public Node getRight() {        return right;    }    public void setValue(T value) {        this.value = value;    }    public Node getParent() {        return parent;    }}

这个实现中用到了泛型,可以对多种类型排序,只需要实现comparable接口并实现了compareTo方法。

测试代码

public void test01(){        @SuppressWarnings("unchecked")        int j=0;        String[] strs = new String[1000];        while(j<strs.length){            int len = (int) Math.floor(Math.random()*10+1);            byte[] bytes = new byte[len];            for(int k=0;k<len;k++){                bytes[k] = (byte) Math.floor(Math.random()*26+65);            }            strs[j] = new String(bytes);            j++;        }        HeapSort<String> sort = new HeapSort<String>((List<String>)Arrays.asList(strs));        List<String> list1 = sort.sort();        for(String o:list1){            if(list1.indexOf(o)%10==0){                System.out.println(o.toString()+" ");            }else{                System.out.print(o.toString()+" ");            }        }    }

测试结果

这个实例是纯java面向对象的实现,相比较原生面向过程的实现处理速度回慢,占用资源也多,进攻学习用。如果有什么问题,希望道友们慷慨指正。