堆和堆排序

  1. 定义:二叉堆,每个节点的值大于等于他的两个子节点;
  2. 采用的数据结构:数组,二叉堆层次遍历存放在数组中,通过下标找到孩子、父亲结点,2k、2k+1、k/2,保证对数级别的时间复杂度实现插入(新插入的元素放在数组尾部,逐渐上升,调整维护堆的性质)和删除最大元素(删除堆顶,调整);
  3. 关键操作:
    • Be:数组中从1开始存储元素;
    • 由下至上的堆的有序化:节点比其父节点的值大,需要交换
    • public void exchange(int[] nums,int i,int j){
      	int tmp = nums[i];
      	nums[i] = nums[j];
      	nums[j] = tmp;
      }
      public void swim(int[] nums,int k){
      	while(k>1 && nums[k]>nums[k/2]){
      		exchange(nums,k,k/2);
      		k = k/2;
      	}
      }
    • 由上至下的堆有序化:父节点比孩子节点值小、
    • public void sink(int[] nums,int k,int N){//N元素的个数
      	while(2*k <= N){
      		int j = 2*k;
      		if(j<N && nums[j]<nums[j-1])
      			j++;//j不是最后一个节点,而且他比右节点小,所以这一步找到了最大的孩子
      		if(nums[k] >= nums[j])
      			break;//顺序正确,不需调整
      		exchange(nums,k,j);
      		k = j;
      	}
      }
    • 插入:将元素增加至末尾,增大N,swim调整顺序;
    • 删除最大值:保存最大值nums[1],将nums[N]移动至堆顶,减小N值,重新调整;
    • public void insert(int[] nums,int N,int ele){
      	nums[++N] = ele;
      	swim(nums,N);
      }
      public int delete(int[] nums,int N){
      	int max = nums[N];
      	exchange(nums,1,N);
      	N--;
      	nums[N] = 0;//置空
      	sink(nums,1,N);
      	return max;
      }
  4. 堆的构造与排序
    • N个元素构造堆,一个一个插入已排序的堆中,用swim,复杂度NlogN;
    • public void heap_sort(int[] nums,int N){
      	/*使用sink构造堆,从中间开始,N/2--N之间的都是叶子节点
      	 *如果一个节点的两个子节点都已经是堆了,那么在该节点上调用sink就可以将他们变成一个堆*/
      	for(int k=N/2;k>=1;k--)
      		sink(nums,k,N);
      	/*构造最大堆,将堆顶元素和N交换,N就是最大值了,之后sink维护堆的性质*/
      	while(N > 1){
      		exchange(nums,1,N--);
      		sink(nums,1,N);
      	}
      }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值