内容简介:版权声明:本文为博主原创文章,未经博主允许不得转载。 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约束:泛化与生成模型
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。