.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面试:说下什么是堆和堆排序?
堆是什么? 堆是基于树抽象数据类型的一种特殊的数据结构,用于许多算法和数据结构中.一个常见的例子就是优先队列,还有排序算法之一的堆排序.这篇文章我们将讨论堆的属性.不同类型的堆以及堆的常见操作.另外我 ...
随机推荐
- OC - 缓存 - NSCache - 介绍
- [leetcode]236. Lowest Common Ancestor of a Binary Tree 二叉树最低公共父节点
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- php加速缓存器opcache,apc,xcache,eAccelerator
一.opcache opcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能, 存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销. PHP 5. ...
- 关于前一篇innodb自增列自己的一点补充
上篇文章是我转载的,忘记注明了出处,在这里深感歉意.但是上篇文章中关于自增列预留ID的计算我当时怎么弄明白,后来自己想了想终于想通了,在这里详细解释一下. 我们以一次性插入10行为例,表格如下: 插 ...
- iOS.AVCaptureSession
AVCaptureSession的使用容易freeze的问题 1. http://stackoverflow.com/questions/11905505/avcapturesession-stop- ...
- json.dumps错误:'utf8' codec can't decode byte解决方案-乾颐堂
一次在使用json.dumps()过程中,出现错误提示: ERROR:"UnicodeDecodeError: 'utf8' codec can't decode byte 0xe1 in ...
- 如何看待阿里 AI 每秒制作 8000 张海报?
看了其他设计老师们的回答,给了我一些启发,于是更新一波. 设计本质上是产品和服务的一部分,如果只站在设计师角度看这问题,免不了会有一种被取代的危机感. 来源:千锋UI 但如果站在整个产品和服务的角度 ...
- 《JavaScript DOM编程艺术》笔记
1. 把<script>标签放到HTML文档的最后,<body>标签之前能使浏览器更快地加载页面. 2. nodeType的常见取值 元素节点(1) 属性节点(2) 文本节点( ...
- hadoop群集 启动
###注意:严格按照下面的步骤 .5启动zookeeper集群(分别在itcast04.itcast05.itcast06上启动zk) cd /itcast/zookeeper-/bin/ ./zkS ...
- 【JAVA】通过URLConnection/HttpURLConnection发送HTTP请求的方法(一)
Java原生的API可用于发送HTTP请求 即java.net.URL.java.net.URLConnection,JDK自带的类: 1.通过统一资源定位器(java.net.URL)获取连接器(j ...