.net下使用最小堆实现TopN算法
测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HeapSort
{
class Program
{
static void Main(string[] args)
{
var arr = new int[] { 10, 7, 5 ,1,2,5};
List<int> src = new List<int>(arr);
HeapSort<int> heapSort = new HeapSort<int>((a, b) => { return a - b; }, src);
heapSort.TryAddNumber(6);
heapSort.TryAddNumber(7);
heapSort.TryAddNumber(8);
heapSort.TryAddNumber(9);
heapSort.TryAddNumber(10);
Console.WriteLine(string.Join(",", heapSort.MinHeapsortToDescend().ConvertAll((t) => t.ToString()).ToArray()));
Console.ReadLine();
}
}
}
算法实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HeapSort
{
/// <summary>
/// 使用最小堆算法计算 TopN,参考 http://blog.csdn.net/morewindows/article/details/6709644
/// 最小堆性质:"父结点的键值总是小于或等于任何一个子节点的键值"
/// </summary>
/// <typeparam name="T"></typeparam>
class HeapSort<T>
{
Comparison<T> comparison;
List<T> minHeapList;
public HeapSort(Comparison<T> _comparison, List<T> list)
{
comparison = _comparison;
MakeMinHeap(list);
}
/* 这里只是将最小堆用于计算TopN,因此不需要添加节点
// 新加入i结点 其父结点为(i - 1) / 2
void MinHeapFixup(int i)
{
int parent;
var temp = minHeapList[i];
parent = (i - 1) / 2; //父结点
while (parent >= 0 && i != 0)
{
//if (list[parent] <= temp)
if (comparison(minHeapList[parent], temp) <= 0)
break;
minHeapList[i] = minHeapList[parent]; //把较大的子结点往下移动,替换它的子结点
i = parent;
parent = (i - 1) / 2;
}
minHeapList[i] = temp;
}
//在最小堆中加入新的数据nNum
void MinHeapAddNumber(int n, T nNum)
{
minHeapList[n] = nNum;
MinHeapFixup(n);
}*/
// 从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
void MinHeapFixdown(int i, int n)
{
int leftChild;
var temp = minHeapList[i];
leftChild = 2 * i + 1;
while (leftChild < n)
{
//if (leftChild + 1 < n && a[leftChild + 1] < a[leftChild]) //在左右孩子中找最小的
if (leftChild + 1 < n && comparison(minHeapList[leftChild + 1], minHeapList[leftChild]) < 0) //在左右孩子中找最小的
leftChild++;
//if (a[leftChild] >= temp)
if (comparison(minHeapList[leftChild], temp) >= 0)
break;
minHeapList[i] = minHeapList[leftChild]; //把较小的子结点往上移动,替换它的父结点
i = leftChild;
leftChild = 2 * i + 1;
}
minHeapList[i] = temp;
}
/* 在TopN中不需要这样做
//在最小堆中删除数
void MinHeapDeleteNumber(int n)
{
Swap(0, n - 1);
MinHeapFixdown(0, n - 1);
}
*/
/// <summary>
/// 尝试添加节点,如果小于等于最小根,不处理
/// </summary>
/// <param name="item"></param>
public void TryAddNumber(T item)
{
if (comparison(minHeapList[0], item) >= 0)//如果小于等于最小根,不处理
{
return;
}
minHeapList[0] = item;//直接覆盖根节点,然后向下比较,以确保最小堆性质:"父结点的键值总是小于或等于任何一个子节点的键值"
MinHeapFixdown(0, minHeapList.Count);
}
/// <summary>
/// 排序建立最小堆
/// </summary>
void MakeMinHeap(List<T> list)
{
minHeapList = list;
for (int i = list.Count / 2 - 1; i >= 0; i--)
MinHeapFixdown(i, list.Count);
}
void Swap(int index1, int index2)
{
var temp = minHeapList[index1];
minHeapList[index1] = minHeapList[index2];
minHeapList[index2] = temp;
}
/// <summary>
/// 排序,在插入未完成之前,千万不要调用排序,这会破坏最小堆的性质
/// </summary>
public List<T> MinHeapsortToDescend()
{
for (int i = minHeapList.Count - 1; i >= 1; i--)
{
Swap(i, 0);
MinHeapFixdown(0, i);
}
return minHeapList;
}
}
}
.net下使用最小堆实现TopN算法的更多相关文章
- 使用最小堆优化Dijkstra算法
OJ5.2很简单,使用priority_queue实现了最小堆竟然都过了OJ……每次遇到relax的问题时都简单粗暴地重新push进一个节点…… 然而正确的实现应该是下面这样的吧,关键在于swap堆中 ...
- Python3实现最小堆建堆算法
今天看Python CookBook中关于“求list中最大(最小)的N个元素”的内容,介绍了直接使用python的heapq模块的nlargest和nsmallest函数的解决方式,记得学习数据结构 ...
- libevent中最小堆实现算法解析
libevent,一个非常好的c的网络库,最近开始学习并分析下,做个记录.源码选用的1.4版本.因为感觉这版的代码比较精简,也没有太多宏定义,个人感觉适合学习原理. 从哪里开始呢,我选择从一些最简单的 ...
- [算法]体积不小于V的情况下的最小价值(0-1背包)
题目 0-1背包问题,问要求体积不小于V的情况下的最小价值是多少. 相关 转移方程很容易想,初始化的处理还不够熟练,可能还可以更简明. 使用一维dp数组. 代码 import java.util.Sc ...
- My集合框架第五弹 最小堆
二叉堆(以最小堆为例),其具有结构性质和堆序性质结构性质: 堆是一棵完全的二叉树,一颗高为h的完全二叉树有2^h到2^h-1个节点,高度为log N 而且该结构可以很容易的使用数 ...
- Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序
前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的re ...
- 多线程外排序解决大数据排序问题2(最小堆并行k路归并)
转自:AIfred 事实证明外排序的效率主要依赖于磁盘,归并阶段采用K路归并可以显著减少IO量,最小堆并行k路归并,效率倍增. 二路归并的思路会导致非常多冗余的磁盘访问,两组两组合并确定的是当前的相对 ...
- C语言实现哈夫曼编码(最小堆,二叉树)
// 文件中有通过QT实现的界面#include <stdio.h> #include <stdlib.h> #include <string.h> typedef ...
- PHP面试:说下什么是堆和堆排序?
堆是什么? 堆是基于树抽象数据类型的一种特殊的数据结构,用于许多算法和数据结构中.一个常见的例子就是优先队列,还有排序算法之一的堆排序.这篇文章我们将讨论堆的属性.不同类型的堆以及堆的常见操作.另外我 ...
随机推荐
- oracle 将逗号分隔的字符串转成多行记录
, rownum), length(, rownum, length(replace('a,b,c,d', ',', '')), length('a,b,c,d') from dual connect ...
- 判断浏览器是ie9座特殊处理
function ie(){ var agent = navigator.userAgent.toLowerCase();//判断浏览器版本 return (!!window.ActiveXObjec ...
- @RequestMapping 介绍
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径. RequestMapping注解有六个属性,下面我们把她 ...
- [Groovy] 学习Groovy的好网站(内容全面)
https://www.tutorialspoint.com/groovy/index.htm
- 为什么const对象只能调用const成员函数,而不能调用非const成员函数?
在c++中,我们可以用const来定义一个const对象,const对象是不可以调用类中的非const成员函数,这是为什么呢?下面是我总结的一些原理. 假设有一个类,名字为test代码如下: clas ...
- 2018.10.13 bzo1934: [Shoi2007]Vote 善意的投票(最小割)
传送门 最小割定义题. 按照题意建边就行了. 考虑把冲突变成把aaa选入不与自己匹配的集合所需要付出的代价. 然后跑最小割就行了. 代码: #include<bits/stdc++.h> ...
- 2018.09.10 bzoj1855: [Scoi2010]股票交易(单调队列优化dp)
传送门 单调队列优化dp好题. 有一个很明显的状态设置是f[i][j]表示前i天完剩下了j分股票的最优值. 显然f[i][j]可以从f[i-w-1][k]转移过来. 方程很好推啊. 对于j<kj ...
- 2018.07.09 洛谷P2365 任务安排(线性dp)
P2365 任务安排 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间 ...
- py-函数基础
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 1.减少重复代码2.使程序变的可扩展3.使程序变得易维护 函数参数 形参变量 只有在被调 ...
- b4和tncl_extract_UNCL_new
# -*- coding:utf-8 -*- import re ''' 适应新版本 注意: 1)17A文件改完后缀后,需要转为UTF-8无BOM格式,才能正确处理. 2)fr = open(file ...