前置基础:
1、向上调整大根堆
已知数组arr,它的排列顺序为大根堆时,加入一个新的数,如何能让整个数组的排列顺序变成大根堆?
public static void heapinsert(int i) {
while (arr[i] > arr[(i - 1) / 2]) { //下标(i - 1) / 2为下标i的父节点
swap(i, (i - 1) / 2);
i = (i - 1) / 2;
}
}
public static void swap(int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
向上调整大根堆,时间复杂度为O(logN)。
2、向下调整大根堆
已知数组arr,它的排列顺序为大根堆时,第一个数变笑了,如果调整使它重新变成大根堆?
public static void heapify(int i, int size) { //size表示这个数组大根堆中节点的个数
int l = i * 2 + 1;
while (l < size) {
int best = l + 1 < size && arr[l+1] > arr[l] ? l+1 : l;
best = arr[best] > arr[i] ? best : i;
if (best == i) {
break;
}
swap(i, best);
i = best;
l = i * 2 + 1;
}
}
public static void swap (int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
向下调整大根堆,时间复杂度为O(logN)。
堆排序
堆排序java代码
public class HeapSort {
public static int MAXN = 100001;
public static int[] arr = new int[MAXN];
public static int n;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
n = (int) in.nval;
for (int i = 0; i < n; i++) {
in.nextToken();
arr[i] = (int) in.nval;
}
// heapSort1();
heapSort2();
for (int i = 0; i < n - 1; i++) {
out.print(arr[i] + " ");
}
out.println(arr[n - 1]);
out.flush();
out.close();
br.close();
}
public static void heapinsert(int i) {
while (arr[i] > arr[(i - 1) / 2]) { //下标(i - 1) / 2为下标i的父节点
swap(i, (i - 1) / 2);
i = (i - 1) / 2;
}
}
public static void heapify(int i, int size) { //size表示这个数组大根堆中节点的个数
int l = i * 2 + 1;
while (l < size) {
int best = l + 1 < size && arr[l+1] > arr[l] ? l+1 : l;
best = arr[best] > arr[i] ? best : i;
if (best == i) {
break;
}
swap(i, best);
i = best;
l = i * 2 + 1;
}
}
public static void swap(int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//从顶到底建立大根堆过程,时间复杂度O(NlogN);
//交换并向下调整大根退过程,时间复杂度O(NlogN);
//故总体的时间复杂度O(NlogN);
public static void heapSort1 () {
//从顶到底建立大根堆
for (int i = 0; i < n; i++){
heapinsert(i);
}
//大根堆的第一个数一定是最大的数,将其与最后一个位置交换
int size = n;
while (size > 1) {
swap(0, --size);
heapify(0, size);
}
}
//从底到顶建立大根堆过程,时间复杂度O(NlogN);
//交换并向下调整大根退过程,时间复杂度O(NlogN);
//故总体的时间复杂度O(NlogN);
public static void heapSort2() {
//从底到顶建立大根堆
int size = n;
for (int i = n - 1; i >= 0; i--) {
heapify(i, size);
}
//大根堆的第一个数一定是最大的数,将其与最后一个位置交换
while (size > 1) {
swap(0, --size);
heapify(0, size);
}
}
}