测试代码:
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 src = new List (arr); HeapSort heapSort = new HeapSort ((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{ ////// 使用最小堆算法计算 TopN,参考 http://blog.csdn.net/morewindows/article/details/6709644 /// 最小堆性质:"父结点的键值总是小于或等于任何一个子节点的键值" /// ///class HeapSort { Comparison comparison; List minHeapList; public HeapSort(Comparison _comparison, List 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); } */ /// /// 尝试添加节点,如果小于等于最小根,不处理 /// /// public void TryAddNumber(T item) { if (comparison(minHeapList[0], item) >= 0)//如果小于等于最小根,不处理 { return; } minHeapList[0] = item;//直接覆盖根节点,然后向下比较,以确保最小堆性质:"父结点的键值总是小于或等于任何一个子节点的键值" MinHeapFixdown(0, minHeapList.Count); } ////// 排序建立最小堆 /// void MakeMinHeap(Listlist) { 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; } /// /// 排序,在插入未完成之前,千万不要调用排序,这会破坏最小堆的性质 /// public ListMinHeapsortToDescend() { for (int i = minHeapList.Count - 1; i >= 1; i--) { Swap(i, 0); MinHeapFixdown(0, i); } return minHeapList; } }}