记得大学时候上过数据结构的课程,对于堆排序一直不太明白,最近看设计模式,其中有组合模式,刚好设计到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;
}
}