使用堆排序,排序依据为文件名的hashcode
/**
* 堆排序方法
* */
public void heapSort(List<ScanFileUnit> arr) {
//构造大根堆
heapInsert(arr);
int size = arr.size();
while (size > 1) {
//固定最大值
swap(arr, 0, size - 1);
size--;
//构造大根堆
heapify(arr, 0, size);
}
}
//构造大根堆(通过新插入的数上升)
public void heapInsert(List<ScanFileUnit> arr) {
for (int i = 0; i < arr.size(); i++) {
//当前插入的索引
int currentIndex = i;
//父结点索引
int fatherIndex = (currentIndex - 1) / 2;
//如果当前插入的值大于其父结点的值,则交换值,并且将索引指向父结点
//然后继续和上面的父结点值比较,直到不大于父结点,则退出循环
while (arr.get(currentIndex).inode > arr.get(fatherIndex).inode) {
//交换当前结点与父结点的值
swap(arr, currentIndex, fatherIndex);
//将当前索引指向父索引
currentIndex = fatherIndex;
//重新计算当前索引的父索引
fatherIndex = (currentIndex - 1) / 2;
}
}
}
//将剩余的数构造成大根堆(通过顶端的数下降)
public void heapify(List<ScanFileUnit> arr, int index, int size) {
//n层的第m个点 index+1=2^(n-1)+m
//则其子节点为第n+1层的2m-1和2m left+1=2^n+2m-1=2*index+2-1=2*index+1 right=left+1
int left = 2 * index + 1;
int right = 2 * index + 2;
while (left < size) {
int largestIndex;
//判断孩子中较大的值的索引(要确保右孩子在size范围之内)
if (arr.get(left).inode < arr.get(right).inode && right < size) {
largestIndex = right;
} else {
largestIndex = left;
}
//比较父结点的值与孩子中较大的值,并确定最大值的索引
if (arr.get(index).inode > arr.get(largestIndex).inode) {
largestIndex = index;
}
//如果父结点索引是最大值的索引,那已经是大根堆了,则退出循环
if (index == largestIndex) {
break;
}
//父结点不是最大值,与孩子中较大的值交换
swap(arr, largestIndex, index);
//将索引指向孩子中较大的值的索引
index = largestIndex;
//重新计算交换之后的孩子的索引
left = 2 * index + 1;
right = 2 * index + 2;
}
}
//交换数组中两个元素的值
public void swap(List<ScanFileUnit> arr, int i, int j) {
ScanFileUnit temp = arr.get(i);
arr.set(i, arr.get(j));
arr.set(j,temp);
}