自主实现的Java实现的构造大小堆、堆排序的算法

    记得大学时候上过数据结构的课程,对于堆排序一直不太明白,最近看设计模式,其中有组合模式,刚好设计到Tree构造,于是一时兴起,写了关于构造堆以及堆排序的算法

    写算法之前,看了看堆的定义,实质是完全二叉树,此定义可以参考http://zh.wikipedia.org/wiki/%E5%A0%86_(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84)

    

    1、构建堆

     在构建堆前,我们需要定义一个数据结构,先来个BinaryTreeItem类

     package com.forever.sort.entity;


/**
 * Created with IntelliJ IDEA.
 * User: qinwenchao01
 * Date: 13-9-25
 * Time: 下午4:30
 */
public class BinaryTreeItem {
    public int value;
    public BinaryTreeItem parent;
    public BinaryTreeItem leftChild;
    public BinaryTreeItem rightChild;


    public void init() {
        parent = null;
        leftChild = null;
        rightChild = null;
        value = -1;
    }


    public BinaryTreeItem(int value) {
        init();
        this.value = value;
    }
}

代码如上,即一个节点中,含有父亲节点的引用,含有左子节点引用,右子节点引用,还有值

 

现在用数组来构建一个堆   

int nums[] = {6, 4, 1, 2, 8, 4, 7, 3, 0, 9, 22, 34, 267, 21, 78, 44, 57, 89, 43};

List<BinaryTreeItem> datas = new ArrayList<BinaryTreeItem>();

      for (int i = 0; i < nums.length; i++) {
            BinaryTreeItem item = new BinaryTreeItem(nums[i]);
            datas.add(item);
        }

现在把数组的值都生成了BinaryTreeItem对象了。

下一步,用List生成一个堆

 if (datas == null)
            return;
        for (int i = 1; i <= datas.size(); i++) {
            //parent
            BinaryTreeItem curItem = datas.get(i - 1);
            //add leftChild
            if (i * 2 <= datas.size()) {
                BinaryTreeItem leftTreeItem = datas.get(i * 2 - 1);
                leftTreeItem.parent = curItem;
                curItem.leftChild = leftTreeItem;
            }
            //add rightChild
            if (i * 2 + 1 <= datas.size()) {
                BinaryTreeItem rightTreeItem = datas.get(i * 2);
                rightTreeItem.parent = curItem;
                curItem.rightChild = rightTreeItem;
            }
        }

这样datas里面各个BinaryTreeItem就关联起来了

然后开始生成最大堆

算法:

         1、逆序遍历datas    for (int i = datas.size() - 1; i >= 0; i--) 

         2、比较i节点与i父亲节点的大小

               1) 若i节点值大 

                    swap两者,并重置相关联节点的关联情况。

                    交换后的处于i位置节点与i的左右子节点比较,子节点不为空且i节点值小于子节点j,则swap i节点与比较的子节点j  重置关联关系  i=j 继续此步骤

                2)若小

                    返回


最大堆生成后,进行堆排序,算法自己想的,基于子堆的比较

思路          

1、用一个List存储有序BinaryTreeItem,从大到小

2、用一个List存储当前比较的BinaryTreeItem

3、在当前比较的List中找出一个最大值,将其加入有序List,将其从比较List中删除,若将其左右子节点非空,加入比较List

4、重复3 直到比较List为空,则排序结束


在我的算法中,构造大根堆和堆排序,都没有用到递归算法。


后面是具体代码:BinaryTreeItem类在前面已有,下面代码是除类定义外其余代码,自行实现了大根堆和小根堆,以及堆排序


package com.forever.sort;


import com.forever.sort.entity.BinaryTreeItem;


import java.util.ArrayList;
import java.util.List;


/**
 * Created with IntelliJ IDEA.
 * User: qinwenchao01
 * Date: 13-9-25
 * Time: 下午4:20
 */
public class MySort {
    public static void main(String[] args) {
        boolean MaximumHeap = false;
        List<BinaryTreeItem> datas = new ArrayList<BinaryTreeItem>();
        int nums[] = {6, 4, 1, 2, 8, 4, 7, 3, 0, 9, 22, 34, 267, 21, 78, 44, 57, 89, 43};
        //prepare data
        initial(datas, nums);
        //make perfect binary tree
        generateHeap(datas);
        //generateSHeap
        generateSHeap(datas, MaximumHeap);
        List<BinaryTreeItem> sList = sortSHeap(datas.get(0), MaximumHeap);
        for (int i = 0; i < datas.size(); i++) {
            System.out.println(datas.get(i).value);
        }
        System.out.println("***********************************");
        for (int i = 0; i < sList.size(); i++) {
            System.out.println(sList.get(i).value);
        }
        generateHeap(sList);
        System.out.println("***********************************");
    }


    public static void initial(List<BinaryTreeItem> datas, int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            BinaryTreeItem item = new BinaryTreeItem(nums[i]);
            datas.add(item);
        }
    }


    public static List<BinaryTreeItem> sortSHeap(BinaryTreeItem parent, boolean isMaximumHeap) {
        List<BinaryTreeItem> results = new ArrayList<BinaryTreeItem>();
        List<BinaryTreeItem> temps = new ArrayList<BinaryTreeItem>();
        temps.add(parent.leftChild);
        temps.add(parent.rightChild);
        results.add(parent);
        while (temps.size() > 0) {
            BinaryTreeItem temp = findSuitable(temps, isMaximumHeap);
            results.add(temp);
            temps.remove(temp);
            if (temp.leftChild != null) {
                temps.add(temp.leftChild);
            }
            if (temp.rightChild != null) {
                temps.add(temp.rightChild);
            }
        }
        return results;
    }


    public static BinaryTreeItem findSuitable(List<BinaryTreeItem> list, boolean isMaximumHeap) {
        BinaryTreeItem temp = null;
        for (int i = 0; i < list.size(); i++) {
            if (temp == null) {
                temp = list.get(i);
            } else {
                if (isMaximumHeap == true) {
                    if (temp.value < list.get(i).value) {
                        temp = list.get(i);
                    }
                }
                if (isMaximumHeap == false)
                    if (temp.value > list.get(i).value) {
                        temp = list.get(i);
                    }
            }
        }
        return temp;
    }




    public static void generateSHeap(List<BinaryTreeItem> datas, boolean isMaximumHeap) {
        for (int i = datas.size() - 1; i >= 0; i--) {
            BinaryTreeItem curItem = datas.get(i);
            if (Compare(curItem, curItem.parent, isMaximumHeap) == true) {
                BinaryTreeItem changedItem = swap(curItem, curItem.parent, datas);
                while (changedItem != null) {
                    changedItem = findPosition(changedItem, datas, isMaximumHeap);
                }
            }
        }
    }


    public static BinaryTreeItem findPosition(BinaryTreeItem changedItem, List datas, boolean isMaximumHeap) {
        if (changedItem.rightChild != null) {
            if (Compare(changedItem.rightChild, changedItem, isMaximumHeap)) {
                swap(changedItem.rightChild, changedItem, datas);
                return changedItem;
            }
        }
        if (changedItem.leftChild != null) {
            if (Compare(changedItem.leftChild, changedItem, isMaximumHeap)) {
                swap(changedItem.leftChild, changedItem, datas);
                return changedItem;
            }
        }
        return null;
    }


    public static void generateHeap(List<BinaryTreeItem> datas) {
        if (datas == null)
            return;
        for (int i = 1; i <= datas.size(); i++) {
            //parent
            BinaryTreeItem curItem = datas.get(i - 1);
            //add leftChild
            if (i * 2 <= datas.size()) {
                BinaryTreeItem leftTreeItem = datas.get(i * 2 - 1);
                leftTreeItem.parent = curItem;
                curItem.leftChild = leftTreeItem;
            }
            //add rightChild
            if (i * 2 + 1 <= datas.size()) {
                BinaryTreeItem rightTreeItem = datas.get(i * 2);
                rightTreeItem.parent = curItem;
                curItem.rightChild = rightTreeItem;
            }
        }
    }


    public static boolean Compare(BinaryTreeItem curItem, BinaryTreeItem parent, boolean isMaximumHeap) {
        if (isMaximumHeap == true)
            return CompareGt(curItem, parent);
        else
            return CompareLt(curItem, parent);
    }


    public static boolean CompareLt(BinaryTreeItem curItem, BinaryTreeItem parent) {
        if (parent == null || curItem == null)
            return false;
        if (parent.value > curItem.value)
            return true;
        return false;
    }


    public static boolean CompareGt(BinaryTreeItem curItem, BinaryTreeItem parent) {
        if (parent == null || curItem == null)
            return false;
        if (parent.value < curItem.value)
            return true;
        return false;
    }


    public static BinaryTreeItem swap(BinaryTreeItem curItem, BinaryTreeItem parent, List<BinaryTreeItem> list) {


        curItem.parent = parent.parent;
        parent.parent = curItem;
        if (curItem == parent.leftChild) {
            BinaryTreeItem parentRightChild = parent.rightChild;
            parent.rightChild = curItem.rightChild;
            parent.leftChild = curItem.leftChild;
            curItem.rightChild = parentRightChild;
            curItem.leftChild = parent;
            if (parentRightChild != null) {
                parentRightChild.parent = curItem;
            }
            int parentIndex = list.indexOf(parent);
            int curIndex = list.indexOf(curItem);
            list.set(parentIndex, curItem);
            list.set(curIndex, parent);
        }
        if (curItem == parent.rightChild) {
            BinaryTreeItem parentLeftChild = parent.leftChild;
            parent.leftChild = curItem.leftChild;
            parent.rightChild = curItem.rightChild;
            curItem.leftChild = parentLeftChild;
            curItem.rightChild = parent;
            if (parentLeftChild != null) {
                parentLeftChild.parent = curItem;
            }
            int parentIndex = list.indexOf(parent);
            int curIndex = list.indexOf(curItem);
            list.set(parentIndex, curItem);
            list.set(curIndex, parent);
        }
        if (curItem.parent != null) {
            if (parent == curItem.parent.leftChild) {
                curItem.parent.leftChild = curItem;
            }
            if (parent == curItem.parent.rightChild) {
                curItem.parent.rightChild = curItem;
            }
        }
        if (parent.leftChild != null) {
            parent.leftChild.parent = parent;
        }
        if (parent.rightChild != null) {
            parent.rightChild.parent = parent;
        }
        return parent;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值