4. 堆排序
堆排序有两种方式:
1)首先创建一个最小堆,将顶部元素输出存入一个新的数组中,然后把堆中最后一个元素移到堆顶,将堆顶元素做向下调整,调整完后堆顶元素就是最小值,再输出存入数组中,如此循环,最终存放在新数组中的数就是按从小到大排好序的了。这种方法的时间复杂度为O(NlogN)
2)更好的方法是建立一个最大堆,然后将堆顶元素和队列中最后一个元素交换位置,因为是从小到大排序,交换之后最大节点就到队列最后了。然后将队列的长度减一,对堆顶元素做向下调整。重复以上过程,直至队列中只剩堆顶元素,此时队列中的元素就是从小到大排好序的了。
两种堆排序的代码如下:
Java:
法1:
//堆排序的第一种方法 static int[] heapSort() { createSmallHeap(); int[] res = new int[n]; //创建一个数组,存储每次输出的最小值 int i = 0; //创建一个变量,表示每次循环要输入到结果数组中的元素在结果数组中的下标 while (n - 1 > 0) { //起始状态是一个最小堆,先把堆顶元素输出,保存在结果数组中,然后把最后一个节点移到根节点上,对根节点做向下调整,重复以上过程 int tem = heap[0]; res[i] = tem; //将堆顶元素存储到结果数组中 i ++; heap[0] = heap[n - 1];//将堆中最后一个节点放到堆顶 n --;//节点中最小的节点被输入到了结果数组,堆的长度减1 siftBigDown(0, n);//需要通过对堆顶节点使用向下调整将最小值调整到堆顶 } res[i] = heap[0];//while结束循环之后,堆中还剩一个节点,将这个元素放在结果数组末尾,此时,结果数组中的数就是按从小到大排好序的 return res; }
法2:
//堆排序的第二种方法 static void heapSortBetter() { //建立最大堆,将堆顶节点与末尾节点交换,队列长度减一,再对交换之后的堆顶节点做向下调整,如此循环,直至队列长度为1 createBigHeap(); while (n > 1) { //循环直到队列长度为1(只有一个节点)时停止,剩下的这一个节点就是最小值 swap(0, n - 1); n --; siftSmallDown(0, n); } }