1.堆排序
堆排序的思路比较简单,首相将n个元素建成初始堆,由于堆本身的特点(以大顶堆为例),堆顶元素就是最大值。输出堆顶元素后,通常将堆底元素送上堆顶,此时根节点已不满足大顶堆的性质。堆被破坏, 将堆顶元素向下调整使其继续保持大顶堆的性质,再输出堆项元素。如此重复,直到堆中仅剩一个元素为止。可见堆排序需要解决两个问题。如何将无序序列构造成初始堆?②输出堆顶元素后,如何将剩余元素调整成新的堆?
堆排序的关键是构造初始堆。n个结点的完全二叉树,最后一个结点是第n/2向下取整个结点的孩子。对第n/2向下取整个结点为根的子树筛选,(对于大根堆,若根结点的关键字小于左右孩子中关键字较大者则交换),使该子树成为堆。之后向前依次对各结点(n/2-1 ~ 1)为根的子树进行筛选,看该结点值是否大于其左右子结点的值,若不大于,则将左右子结点中的较大值与之交换,交换后可能会破坏下一级的堆,于是继续采用上述方法构造下一级的堆, 直到以该结点为根的子树构成堆为止。反复利用上述调整堆的方法建堆,直到根结点。至此该完全二叉树满足堆的定义。
2.代码
/**
*
***********************************
* @Title: heapSort
* @Description:
* @param:
* @return: void
***********************************
*/
public void heapSort() {
DataNode tempNode;
// Step 1 construct the initial heap
for(int i = length / 2 - 1; i >= 0; i--) {
adjustHeap(i,length);
}//Of for i
System.out.println("The initial heap: " + this + "\r\n");
//Step 2 swap and reconstruct.
for(int i = length -1; i > 0; i--) {
tempNode = data[0];
data[0] = data[i];
data[i] = tempNode;
adjustHeap(0,i);
System.out.println("Round " + (length - i) + ": " + this);
}// Of for i
}//Of heapSort
/**
*
***********************************
* @Title: adjustHeap
* @Description:
* @param: @param paraStart
* @param: @param paraLength
* @return: void
***********************************
*/
public void adjustHeap(int paraStart, int paraLength) {
DataNode tempNode = data[paraStart];
int tempParent = paraStart;
int tempKey = data[paraStart].key;
for(int tempChild = paraStart * 2 + 1; tempChild < paraLength; tempChild = tempChild * 2 + 1) {
if(tempChild +1 < paraLength) {
if(data[tempChild].key < data[tempChild + 1].key){
tempChild++;
}//Of if
}//Of if
System.out.println("The parent position is " + tempParent + " and the child is " + tempChild);
if(tempKey < data[tempChild].key) {
//the child is bigger.
data[tempParent] = data[tempChild];
System.out.println("Move " + data[tempChild].key + " to position " + tempParent);
tempParent = tempChild;
}
else {
break;
}//of if
}//of for tempChild
data[tempParent] = tempNode;
System.out.println("Adjust " + paraStart + " to " + paraLength + ": " + this);
}//Of adjustHeap
public static void heapSortTest() {
int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
tempDataArray.heapSort();
System.out.println("Result\r\n" + tempDataArray);
}// Of heapSortTest
/**
*
***********************************
* @Title: main
* @Description:
* @param: @param args
* @return: void
***********************************
*/
public static void main(String args[]) {
System.out.println("\r\n-------heapSortTest-------");
heapSortTest();
}// Of main
3.总结
堆排序的难度还是挺大的,建堆时间O(n),然后有n-1次向下调整操作,每次调整的时间复杂度为O(h),平均时间复杂度为O(nlog2n)。