堆排序(非递归版本)

import java.util.Arrays;

public class Main {

	/**
	 * @param args
	 */
	//堆排序
	//原理 先构建一个构建一个都是大根堆的完全二叉树
	//		5  
	//    3    4   
	//  1   2
	//一颗二叉树  父节点永远比两个子节点都大。这个叫做大根堆
	
	//时间复杂度 O(N*logN)
	//空间复杂度O(1)//
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = {5,1,95,998,1,0,-5,-3,1,-5,8};
		//脑补
		//假装 arr数组是一个二叉树
		//他的坐标 0是根节点    子节点分别是坐标值 
		//左:index*2+1 右 index*2+2
		//父节点 为 子节点 坐标 (index-1)/2
		
		heapSort(arr);
		System.out.println(Arrays.toString(arr));
	}
	
	public static void heapSort(int[] arr){//不需要递归
		if(arr==null||arr.length==1){
			return;
		}
		for(int i=0;i<arr.length;i++){//构建一个大根堆
			heapInsert(arr,i);
		}
		//遍历完刚好建立一个大根堆
		int size = arr.length; //数组长度
		swap(arr,0,--size);//把我们脑补的二叉树根节点 最一个孩子节点进行交换   --根节点一定是数组中最大的
		//此时我们已经找到了数组中最大的值 那么下次行为将只会操作 N-1长度的数组
		
		while(size>0){//重复一个过程找到所有的最大值并放到数组最后
			heapify(arr, 0, size);
			swap(arr,0,--size);
		}
		
		
	}
	
	public static void heapInsert(int[] arr,int index){//
		while(arr[index]>arr[(index-1)/2]){//如果这个节点比父节点小  (0-1)/2==0  如果index是0的话不会循环
			swap(arr,index,(index-1)/2);  //将比父节点小的值交换给父节点
			index = (index-1)/2; //index =父节点 看看这个节点是不是比他的父节点要大
		}
	}
	public static void heapify(int[] arr,int index,int size){
		//大根堆二叉树的根节点 交换后大根堆已经被破坏
		// 需要重新通过交换 来把二叉树变成大根堆
		int left = index*2+1;//左孩子
		while(left<size){
			//left+1是右节点  首先应该判断一下右节点存在不存在
			//然后 判断 左节点和右节点那个值大 largest = 下标
			int largest = left+1<size &&arr[left+1]>arr[left]?left+1:left;
			
			//判断比较大的那个子节点 是否大于他们的父节点
			largest = arr[largest]>arr[index]?largest:index;
			if(largest==index){
				break;
				//父节点大于最大的根节点
				//终止 大根堆修复完成
			}
			
			//如果没有终止的话
			//说明父节点小于根节点
			//把他们位置交换 让大的数当父节点
			swap(arr,largest,index);
			//继续向下找
			index=largest;
			left = index*2+1;
		}
	}
	
	
	public static void swap(int[] a,int i,int j){
		int temp = a[i];
		a[i] = a[j];
		a[j]=temp;
	}
	

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值