.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面试:说下什么是堆和堆排序?
堆是什么? 堆是基于树抽象数据类型的一种特殊的数据结构,用于许多算法和数据结构中.一个常见的例子就是优先队列,还有排序算法之一的堆排序.这篇文章我们将讨论堆的属性.不同类型的堆以及堆的常见操作.另外我 ...
随机推荐
- 安全运维 -- Linux服务器使用公私钥密匙证书登录
环境:Ubuntu 16 前言 黑客遍地都是,ssh/pop3/ftp等爆破工具的流行让站长的日常运维工作量大大加重.Metasplot,Bruter等工具更是针对以上协议有专门 的破解方法,有字典破 ...
- socket编程介绍
Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中心类,可以简化网络 ...
- Executor(二)ThreadPoolExecutor、ScheduledThreadPoolExecutor 及 Executors 工厂类
Executor(二)ThreadPoolExecutor.ScheduledThreadPoolExecutor 及 Executors 工厂类 Java 中的线程池类有两个,分别是:ThreadP ...
- 共享内存system v(未编译)
#include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> ...
- ubuntu16下Elasticsearch5.1.1安装部署
本人在安装es5.1.1版本时候整理的一些过程,参照了网上部分过程:其中过程中也出现一些其它问题,出现的问题和解决方案都整理在此文中. 1Elasticsearch5.1.1安装 到ES官网https ...
- C语言基础第二次作业
PTA第一次作业 题目7-1 统计学生成绩 1.实验代码 #include<stdio.h> int main(void){ ,B=,C=,D=,E=,f; scanf("%d ...
- 为了记忆和方便翻阅 vue构建后的结构目录说明
一. ├── build // 项目构建(webpack)相关代码 记忆:(够贱) 9个 │ ├── build.js // 生产环 ...
- input不能输入中文
<input type="text" oninput="this.value = this.value.replace(/[\u4e00-\u9fa5d]/g, ' ...
- 2018.09.27 codeforces1045A. Last chance(线段树优化建图+最大流)
传送门 看完题应该都知道是网络流了吧. 但是第二种武器直接建图会gg. 因此我们用线段树优化建图. 具体操作就是,对于这m个人先建一棵线段树,父亲向儿子连容量为inf的边,最后叶子结点向对应的人连容量 ...
- 2018.09.26 洛谷P2464 [SDOI2008]郁闷的小J(map+vector)
传送门 本来出题人出出来想考数据结构的. 但是我们拥有map+vector/set这样优秀的STL,因此直接用map离散化,vector存下标在里面二分找答案就行了. 代码: #include< ...