二叉堆结构解释: http://www.apkbus.com/android-58533-1-1.html
代码实现方式:
using System; using System.Collections.Generic; namespace BinaryHeap { /// <summary> /// 排序的枚举 /// </summary> public enum Order { ASC = 0, DESC = 1 } /// <summary> /// 二叉堆 /// </summary> /// <typeparam name="T">填入你需要存储的类型</typeparam> public class BinaryHeap<T> where T : IComparable<T> { /// <summary> /// The size of the heap /// </summary> public int Size { get; set; } private int length; /// <summary> /// 堆的长度 /// </summary> public int Length { get { return length; } private set { length = value; } } private T[] Items { get; set; } private Order Order = Order.ASC; /// <summary> /// The Cons of the heap /// </summary> /// <param name="size">The default size of the heap</param> /// <param name="order">The order of the heap</param> public BinaryHeap(int size, Order order) { if (size < 1) { throw new Exception("二叉堆最少长度2"); } this.Size = size; this.Order = order; this.Size++; Items = new T[this.Size]; this.length = 0; } /* 我们可以举一个例子,假设我们已经有了一个最小二叉堆(其中有7个元素),现在我们要插入一个元素17到这个二叉堆中去,那么插入后二叉堆大小就会加一变成8 10 30 20 34 38 30 24 17 现在17位下划线的那个,我们已经将他放在数组的最后位置了,然后我们比较他与他的父节点(位置为8/2 = 4),在位置4(从1开始数)的为34,由于17小于34,所以我们交换彼此,得到下图: 10 30 20 17 38 30 24 34 现在17跑到位置4中去了,然后我们比较17和他的新的父节点(位置为4/2 = 2), 在位置2(从1开始数)的为30,由于17还是小于30,所以交换彼此,得到下图: 10 17 20 30 38 30 24 34 现在17跑到第二位了,继续比较,父节点位置为2/2 = 1,由于17不小于10,所以这里就没有必要比较了,走到这一步我们的新元素17添加完成。现在的堆已经添加了元素17,堆中有8位按照最小二叉堆规则排序的元素。 */ /// <summary> /// 添加节点 /// </summary> /// <param name="item"></param> public void Add(T item) { if (this.length == 0) { Items[1] = item; } else { int len = this.length; if (len >= this.Size) { throw new Exception("二叉堆已经满了,不能再添加了"); } int endPos = len + 1; Items[endPos] = item; //从二叉堆最中间的数字 和 最末尾的数字第一次进行比较 int parentPos = endPos / 2; bool isContinue = true; while (parentPos != 0 && isContinue) { // 升序 if (Order == BinaryHeap.Order.ASC) { //实例比参数小就返回 -1 if (Items[endPos].CompareTo(Items[parentPos]) < 0) { //交换 Swap(ref Items[endPos], ref Items[parentPos]); endPos = parentPos; parentPos = endPos / 2; } else { isContinue = false; } } else { //降序 if (Items[endPos].CompareTo(Items[parentPos]) > 0) { Swap(ref Items[endPos], ref Items[parentPos]); endPos = parentPos; parentPos = endPos / 2; } else { isContinue = false; } } } } this.length++; } /// <summary> /// 删除节点 /// </summary> /// <returns>if the order is ASC, return the smallest one, if DESC, return the largest one.</returns> public T Remove() { if (this.length == 0) { throw new Exception("二叉树为空"); } // 把二叉堆的第一个元素删除掉 T removedItem = Items[1]; int len = this.length; Items[1] = Items[len]; //把末尾的元素添加到第一位 // 减少二叉堆的长度 this.length--; //先计算出第一次比较的两个节点 int currentPos = 1; int leftChildPos = currentPos * 2; int rightChildPos = currentPos * 2 + 1; bool isContinue = true; while ((leftChildPos <= len || rightChildPos <= len) && isContinue) { // Compare the removing item to its childrens, swap each other if needed if (Order == BinaryHeap.Order.ASC) { #region 升序 if (leftChildPos <= len && rightChildPos <= len) { //当左节点小于右节点的时候,当前节点就跟左节点对比(是否交换) if (Items[leftChildPos].CompareTo(Items[rightChildPos]) < 0 && Items[currentPos].CompareTo(Items[leftChildPos]) >= 0) { Swap(ref Items[currentPos], ref Items[leftChildPos]); currentPos = leftChildPos; } //当左节点大于等于右节点的时候,当前节点就跟右节点对比(是否交换) else if (Items[leftChildPos].CompareTo(Items[rightChildPos]) >= 0 && Items[currentPos].CompareTo(Items[rightChildPos]) >= 0) { Swap(ref Items[currentPos], ref Items[rightChildPos]); currentPos = rightChildPos; } else { isContinue = false; } } else if (leftChildPos <= len) //左节点比较 { if (Items[currentPos].CompareTo(Items[leftChildPos]) >= 0) { Swap(ref Items[currentPos], ref Items[leftChildPos]); currentPos = leftChildPos; } else { isContinue = false; } } else if (rightChildPos <= len) //右节点比较 { if (Items[currentPos].CompareTo(Items[rightChildPos]) >= 0) { Swap(ref Items[currentPos], ref Items[rightChildPos]); currentPos = rightChildPos; } else { isContinue = false; } } else { isContinue = false; } #endregion leftChildPos = currentPos * 2; rightChildPos = currentPos * 2 + 1; } else { #region 降序 if (leftChildPos <= len && rightChildPos <= len) { if (Items[leftChildPos].CompareTo(Items[rightChildPos]) > 0 && Items[currentPos].CompareTo(Items[leftChildPos]) <= 0) { Swap(ref Items[currentPos], ref Items[leftChildPos]); currentPos = leftChildPos; } else if (Items[leftChildPos].CompareTo(Items[rightChildPos]) <= 0 && Items[currentPos].CompareTo(Items[rightChildPos]) <= 0) { Swap(ref Items[currentPos], ref Items[rightChildPos]); currentPos = rightChildPos; } else { isContinue = false; } } else if (leftChildPos <= len) { if (Items[currentPos].CompareTo(Items[leftChildPos]) <= 0) { Swap(ref Items[currentPos], ref Items[leftChildPos]); currentPos = leftChildPos; } else { isContinue = false; } } else if (rightChildPos <= len) { if (Items[currentPos].CompareTo(Items[rightChildPos]) <= 0) { Swap(ref Items[currentPos], ref Items[rightChildPos]); currentPos = rightChildPos; } else { isContinue = false; } } else { isContinue = false; } #endregion leftChildPos = currentPos * 2; rightChildPos = currentPos * 2 + 1; } } return removedItem; } /// <summary> /// 排序二叉堆 /// </summary> /// <returns>Return the sorted heap array</returns> public IEnumerable<T> Sort() { if (this.length == 0) { throw new Exception("The heap is empty"); } while (this.length > 0) { yield return Remove(); } } #region Private method /// <summary> /// Swap each other /// </summary> /// <param name="t1">The first one</param> /// <param name="t2">The second one</param> private void Swap(ref T t1, ref T t2) { T temp = t1; t1 = t2; t2 = temp; } #endregion } }
时间: 2024-10-11 16:15:25