堆及堆排序和应用-go实现

1 堆排序

//heap
/*根据树的性质,树节点前一半一定是分支节点(有孩子),故从这些节点开始调整出初始堆,,len(a)/2-1是第一个非叶子
 */
 func constructHeap(heap []int) {
 	for i:=len(heap)/2-1;i>=0;i-- {
 		adjustHeap(heap,i,len(heap))
	}
 }
 /*每次调整使得满足堆定义
  */
 func adjustHeap(heap []int,start,length int) {
 	var child,i int
 	i=start
 	for {
 		child=i*2+1
 		if child>length-1 {
 			//检查是否越界
 			break
		}
 		if child+1<=length-1&&heap[child]<heap[child+1] {
 			child+=1
		}//find bigger child
		if heap[i]<heap[child] {
			heap[child],heap[i]=heap[i],heap[child]
			/*交换后,以child为根的子树不一定满足堆定义,所以从child处开始调整*/
			i=child
		}else {
			break
		}
	}
 }

 func heapSort(heap []int) {
	 // 构建大顶堆
 	constructHeap(heap)
 	for i:=len(heap)-1;i>=0;i-- {
		/*把根节点跟最后一个元素交换位置,调整剩下的n-1个节点,即可排好序*/
		heap[0],heap[i]=heap[i],heap[0]
		adjustHeap(heap,0,i)
	}
 }

堆的应用:

1 找到数组中第K的最值

数组中的第K的个最大值(小顶堆),有序矩阵的第K小的元素最低加油次数,有序矩阵的第k的最小数组和

2 TOPK

前K个高频元素查找和最小的K对数字前K个高频单词且按顺序返回滑动窗口最大值

3 堆排序

根据字符串出现频率排序合并K个升序的链表

4 一个数组,可能包含连续相同的,将不同字母或数字重新排列使得连元素之间两两不同(输入:[1,1,1,2,2,2] 输出:[2,1,2,1,2,1])

距离相等的条形码重构字符串

5 利用堆求中位数:用一个最大堆存放比中位数小(或等于)的元素,用一个最小堆存放比中位数大(或等于)的元素。这里关键的方法是插入,每当要插入一个元素时,根据判断条件将它插入最大堆或是最小堆,并更新最大堆和最小堆(更新的逻辑很重要),使得最大堆和最小堆中元素的个数之差不超过1,这样中位数就是最大堆或最小堆的堆顶元素。具体而言,当最大堆和最小堆中元素个数不同(个数相差为1)时,元素个数多的那个堆的堆顶元素即为中位数;如果两者元素个数相同,那么中位数可以是最大堆和最小堆的堆顶元素的值取平均。

插入流程(以大堆为基准):

①当最大堆中的元素个数为0(即为空)时,将元素放入其中。(即将第一个元素放入到最大堆)

②当big_heap.size() == small_heap.size()时,比较最大堆的堆顶元素与将放入的元素大小,如果小于其堆顶的元素,则直接放入到最大堆中,否则放入到最小堆中。

③当big_heap.size() > small_heap.size()时,还是将放入的元素与最大堆的堆顶元素进行比较,如果大于堆顶元素,直接放入最小堆,否则,将最大堆的堆顶元素push到最小堆中,再将其弹出最大堆,最后将要放入的元素放入到最大堆中。

④当big_heap.size() < small_heap.size()时,则比较最小堆的堆顶元素与放入元素的大小,如果小于最小堆的堆顶元素,则直接放入到最大堆中,否则,将最小堆的堆顶元素放入到最大堆中,再将堆顶元素弹出,将要放入的元素放入到最小堆中。

数据流的中位数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值