堆的概念:
一颗完全树
堆排序就是:就是依次添加的,中间不缺节点,除了最后叶节点不满,别的节点哦都是两个子节点
分为大根堆小根堆
小根堆,每个节点都比它的左右子树的节点要小
大根堆,每个节点都比它的左右子树的节点要大
堆排序的实现:
- 先是读数组中的值构建小顶堆(小顶堆升序,大顶堆降序序列,其实也看怎末写),就是新添的先放最后,跟父节点比较,比父节点小就继续比较,直到根节点。
- 再依次拿堆顶元素,因为堆顶就是最小的,拿完就要调整
- 调整:树最后的元素取代丢掉的堆顶元素,遍历重新整合成小丁堆
堆排序两种实现
- 1.树的实现,依靠先序队列,建堆,要和父节点比较,交换value值,还有指针的指向,依次拿,每次都要
- 2.数组的实现,不用指针,找到下标就可以直接交换值
树和数组之间默认转换就是从左到右,从上到下读取树
数组体现:左孩子2n+1,有孩子2n+2,父亲是(n-1)/2
时间复杂度
构建堆:
1.从数组中取, O(N)
2.建一个堆,每次都和父节点比较,树的深度O(logN)
取堆顶元素:
1.从堆中取根节点取n次 O(N)
2.调整为堆 O(logN)
代码:
package BadaSort.duiPai;
import java.util.Arrays;
/**
* @author Mzh
* @date 2020-06-03 12:52
* @description:
* @version:
*/
public class DuipaiArray {
public static void main(String[] args) {
int[] arr={9,8,7,6,5,4,3,2,1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr){
//构建大顶堆
for(int i=arr.length/2-1;i>=0;--i){
//从第一个非叶子节点从下往上,从右向左调整结构
adjustHeap(arr,i,arr.length);
}
//调整结构+交换堆顶和莫为元素
for (int j=arr.length-1;j>0;j--){
swap(arr,0,j);
adjustHeap(arr,0,j);
}
}
/**
* 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
* @param arr
* @param i
* @param length
*/
public static void adjustHeap(int []arr,int i,int length){
int temp = arr[i];//先取出当前元素i
for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
k++;
}
if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
arr[i] = arr[k];
i = k;
}else{
break;
}
}
arr[i] = temp;//将temp值放到最终的位置
}
//交换
public static void swap(int []arr,int a ,int b){
int temp=arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}