堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。能夠利用數組的特色快速定位指定索引的元素。堆分爲大根堆和小根堆,是徹底二叉樹。大根堆的要求是每一個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,須要使用的就是大根堆,由於根據大根堆的要求可知,最大的值必定在堆頂。下面附上簡單C#簡單實現:算法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Heap { /// <summary> /// 堆排序實現 /// </summary> class HeapSort { public static void Sort<T>(T[] originArr) where T : IComparable { //首先建堆 BuildMaxHeap<T>(originArr); //在一個堆上在進行排序 RealSort<T>(originArr); } private static void RealSort<T>(T[] originArr) where T : IComparable { for (int i = 0; i < originArr.Length-1; i++) { Swap<T>(originArr , 0, originArr.Length - (i+1)); MaxHeapIFY<T>(originArr, originArr.Length - (i + 1), 0); } } /// <summary> /// 1.首先是須要清楚 GetMaxObjInHeap方法的做用,是在一個堆上插入一個值,並保證插入後堆的性質不變 /// 2.堆實際上是知足徹底二叉樹的性質的,也就是 葉子節點 = (總結點+1)/2 或者 總結點 / 2 /// 3.把每一個葉子節點看作一個獨立的最大堆,自底而上構建最大堆 /// </summary> private static void BuildMaxHeap<T>(T[] originArr) where T : IComparable { int len = originArr.Length / 2; for (int i = len; i >= 0 ; i--) { MaxHeapIFY<T>(originArr,originArr.Length, i); } } /// <summary> /// 堆操做中核心方法,並維護最大堆的性質 /// 假設originList是一個最大堆,實如今堆固定位置插入元素,並同時保證最大堆的性質 /// </summary> private static void MaxHeapIFY<T>(T[] originList, int heapSie, int pos) where T : IComparable { int len = heapSie; int largest = 0; int cLeft = pos * 2; int cRight = pos * 2 + 1; while (cLeft < len || cRight < len) { largest = cLeft; if (cRight < len && originList[cLeft].CompareTo(originList[cRight]) < 0) { largest = cRight; } if (originList[pos].CompareTo(originList[largest]) >= 0) { break; } else { Swap<T>(originList, pos, largest); pos = largest; cLeft = pos * 2; cRight = pos * 2 + 1; } } } /// <summary> /// 數組中兩個元素交換 /// </summary> private static void Swap<T>(T[] originList, int posFirst, int posSec) where T : IComparable { T temp = originList[posFirst]; originList[posFirst] = originList[posSec]; originList[posSec] = temp; } public static void PrintArr<T>(T[] arr) { for (int i = 0; i < arr.Length; i++) { Console.Write(arr[i] + " , "); } Console.WriteLine(""); Console.WriteLine("=================="); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Heap { /// <summary> /// 優先隊列實現 /// </summary> class PriorityQueue<T> where T:IComparable { private List<T> queue; public PriorityQueue(int size = 10) { queue = new List<T>(size); } public PriorityQueue<T> Add(T t) { if (queue.Count <= 0) { queue.Add(t); } else { queue.Add(t); HeapIncreaseKey(t, queue.Count -1, true); } return this; } public T Pop() { if (queue.Count <= 0) return default(T); Swap(queue, 0, queue.Count - 1); MaxHeapIFY(queue, queue.Count - 1, 0); T max = queue[queue.Count - 1]; queue.RemoveAt(queue.Count - 1); return max; } /// <summary> /// 堆操做中核心方法,並維護最大堆的性質 /// 假設originList是一個最大堆,實如今堆固定位置插入元素,並同時保證最大堆的性質 /// </summary> private void MaxHeapIFY(List<T> originList, int heapSie, int pos) { int len = heapSie; int largest = 0; int cLeft = pos * 2; int cRight = pos * 2 + 1; while (cLeft < len || cRight < len) { largest = cLeft; if (cRight < len && originList[cLeft].CompareTo(originList[cRight]) < 0) { largest = cRight; } if (originList[pos].CompareTo(originList[largest]) >= 0) { break; } else { Swap(originList, pos, largest); pos = largest; cLeft = pos * 2; cRight = pos * 2 + 1; } } } private void HeapIncreaseKey(T key, int pos, bool isInsert = false) { if (queue.Count <= 0) return; if (key.CompareTo(queue[pos]) < 0 && !isInsert) return; //賦值 queue[pos] = key; //維護堆性質 int parent = Parent(pos); while (parent >= 0 && queue[pos].CompareTo(queue[parent]) > 0) { Swap(queue, pos, parent); pos = parent; parent = Parent(parent); } } private int Parent(int pos) { return pos / 2; } /// <summary> /// 數組中兩個元素交換 /// </summary> private void Swap(List<T> originList, int posFirst, int posSec) { T temp = originList[posFirst]; originList[posFirst] = originList[posSec]; originList[posSec] = temp; } } }