内容简介:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tkokof1/article/details/86752345
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tkokof1/article/details/86752345
本文列出了一种二叉堆的泛化实现方法
所谓二叉堆,其实就是一种完全二叉树或者近似完全二叉树,树中 父节点的键值总是保持某种固定的序关系于任何一个子节点的键值 ,且每个节点的 左子树 和 右子树 也都是 二叉堆 .
这里列出一种二叉堆的泛化实现方法,其中值得一提的地方有这么几处:
- 泛化数据类型,方法自然是使用泛型实现
- 泛化序关系的表达方式,传统的最大堆和最小堆实现一般就是直接使用数值的大小比较,泛化的方法则是使用泛型委托
- 实现了一种类似于空间划分的元素查找方法
完整的代码可以在 gist 上找到:
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;
public class Heap<T> where T : IEquatable<T>
{
public static Heap<T> Build(IEnumerable<T> items, Func<T, T, bool> predicate)
{
var heap = new Heap<T>(predicate);
if (items != null)
{
var iter = items.GetEnumerator();
while (iter.MoveNext())
{
var item = iter.Current;
heap.Add(item);
}
}
return heap;
}
/*
public static Heap<T> Build2(IEnumerable<T> items, Func<T, T, bool> predicate)
{
var heap = new Heap<T>(predicate);
if (items != null)
{
heap.m_items.AddRange(items);
var itemCountIndexBegin = heap.m_items.Count / 2;
var itemCountIndexEnd = 1;
for (int i = itemCountIndexBegin; i >= itemCountIndexEnd; --i)
{
// NOTE this requires Heapify() just do "down-heap" operation
// now Heapify() do both "up-heap" and "down-heap" operation
heap.Heapify(i - 1);
}
}
return heap;
}
*/
Func<T, T, bool> m_predicate;
List<T> m_items = new List<T>();
public int Count
{
get
{
return m_items.Count;
}
}
public ReadOnlyCollection<T> Items
{
get
{
return m_items.AsReadOnly();
}
}
public T this[int index]
{
get
{
return m_items[index];
}
}
public Heap(Func<T, T, bool> predicate)
{
Debug.Assert(predicate != null);
m_predicate = predicate;
}
int IndexOfRecur(T item, int itemIndex)
{
if (IsValidIndex(itemIndex))
{
if (!m_predicate(item, m_items[itemIndex]))
{
// not found
return -1;
}
else
{
if (m_items[itemIndex].Equals(item))
{
return itemIndex;
}
else
{
var itemCountIndex = itemIndex + 1;
var childCountIndexLeft = itemCountIndex * 2;
var childIndexLeft = childCountIndexLeft - 1;
var index = IndexOfRecur(item, childIndexLeft);
if (index >= 0)
{
return index;
}
else
{
var childCountIndexRight = itemCountIndex * 2 + 1;
var childIndexRight = childCountIndexRight - 1;
return IndexOfRecur(item, childIndexRight);
}
}
}
}
// default return -1
return -1;
}
// return -1 when not found(recur)
public int IndexOf(T item)
{
return IndexOfRecur(item, 0);
}
// return -1 when not found(iterator)
public int IndexOf2(T item)
{
return m_items.IndexOf(item);
}
public void Add(T item)
{
m_items.Add(item);
Heapify(m_items.Count - 1);
}
public void Remove(T item)
{
var itemIndex = IndexOf(item);
if (itemIndex >= 0)
{
Swap(itemIndex, m_items.Count - 1);
m_items.RemoveAt(m_items.Count - 1);
Heapify(itemIndex);
}
}
public void RemoveAt(int itemIndex)
{
if (IsValidIndex(itemIndex))
{
Swap(itemIndex, m_items.Count - 1);
m_items.RemoveAt(m_items.Count - 1);
Heapify(itemIndex);
}
}
public void Clear()
{
m_items.Clear();
}
bool IsValidIndex(int itemIndex)
{
return itemIndex >= 0 && itemIndex < m_items.Count;
}
void Swap(int index1, int index2)
{
if (IsValidIndex(index1) && IsValidIndex(index2))
{
var temp = m_items[index1];
m_items[index1] = m_items[index2];
m_items[index2] = temp;
}
}
void Heapify(int itemIndex)
{
if (IsValidIndex(itemIndex))
{
var itemCountIndex = itemIndex + 1;
// first check parent
var parentCountIndex = itemCountIndex / 2;
var parentIndex = parentCountIndex - 1;
if (IsValidIndex(parentIndex) && !m_predicate(m_items[itemIndex], m_items[parentIndex]))
{
while (IsValidIndex(itemIndex) && IsValidIndex(parentIndex) && !m_predicate(m_items[itemIndex], m_items[parentIndex]))
{
Swap(itemIndex, parentIndex);
// update index
itemIndex = parentIndex;
itemCountIndex = itemIndex + 1;
parentCountIndex = itemCountIndex / 2;
parentIndex = parentCountIndex - 1;
}
}
else
{
// then check child
var childCountIndexLeft = itemCountIndex * 2;
var childIndexLeft = childCountIndexLeft - 1;
var childCountIndexRight = itemCountIndex * 2 + 1;
var childIndexRight = childCountIndexRight - 1;
while (IsValidIndex(childIndexLeft))
{
if (IsValidIndex(childIndexRight))
{
if (!m_predicate(m_items[childIndexLeft], m_items[itemIndex]) || !m_predicate(m_items[childIndexRight], m_items[itemIndex]))
{
if (!m_predicate(m_items[childIndexLeft], m_items[itemIndex]) && m_predicate(m_items[childIndexRight], m_items[itemIndex]))
{
Swap(childIndexLeft, itemIndex);
itemIndex = childIndexLeft;
itemCountIndex = childCountIndexLeft;
}
else if (m_predicate(m_items[childIndexLeft], m_items[itemIndex]) && !m_predicate(m_items[childIndexRight], m_items[itemIndex]))
{
Swap(childIndexRight, itemIndex);
itemIndex = childIndexRight;
itemCountIndex = childCountIndexRight;
}
else
{
if (m_predicate(m_items[childIndexLeft], m_items[childIndexRight]))
{
// left should be child
Swap(childIndexRight, itemIndex);
itemIndex = childIndexRight;
itemCountIndex = childCountIndexRight;
}
else
{
// right should be child
Swap(childIndexLeft, itemIndex);
itemIndex = childIndexLeft;
itemCountIndex = childCountIndexLeft;
}
}
// update index
childCountIndexLeft = itemCountIndex * 2;
childIndexLeft = childCountIndexLeft - 1;
childCountIndexRight = itemCountIndex * 2 + 1;
childIndexRight = childCountIndexRight - 1;
}
else
{
// break since fit
break;
}
}
else
{
// right child is invalid, reach end
if (!m_predicate(m_items[childIndexLeft], m_items[itemIndex]))
{
Swap(childIndexLeft, itemIndex);
}
// break since reach end
break;
}
}
}
}
}
}
参考资料
不出意外的话,这应该是 2019 新年之前的最后的一篇博文,来年继续吧~
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【剖析 | SOFARPC 框架】系列之 SOFARPC 泛化调用实现剖析
- 剖析 SOFARPC 框架系列之 SOFARPC 泛化调用实现剖析
- 量化深度强化学习算法的泛化能力
- 使用数据增强技术提升模型泛化能力
- 一个Dubbo泛化调用的Util
- 深度学习中的Lipschitz约束:泛化与生成模型
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
宇宙涟漪中的孩子
谢云宁 / 四川科学技术出版社 / 2017-11 / 28.00元
近未来。日冕科技公司通过建造围绕太阳的光幕搜集了近乎无穷的能源,这些能源主要用于地球上的网络空间建设。随着全球网络时间频率的不断提升,越来越多的人选择接驳进虚拟空间,体验现实中难以经历的丰富人生。 网络互动小说作者宁天穹一直自认为是这些人中普通的一员,有一天却被一名读者带进反抗组织,了解到日冕公司的各种秘密,并被告知自己的小说将在抵抗运动中起到重要作用。 起初他拒绝参与,但看到地球被笼......一起来看看 《宇宙涟漪中的孩子》 这本书的介绍吧!