把算法导论第六章的堆排序用C#实现了一下。 把MaxHeapify用迭代实现了。发现几个问题:
第一呢,算法导论中假设内部数组是从1开始的,结果左右结点的算法和从0开始的数组实际上是不同的。
第二呢,在改迭代的时候,粗心把循环变量写错了。结果调了很久,郁闷死。
并且加入优先级队列的功能,包括Maximum, ExtractMax, IncreaseKey, Insert, Delete子过程
下面是实现的代码:
namespace
FengChen.Practices
...
{ public class Chapter6 ... { public class MaxHeap ... { private Int32[] m_Array; private Int32 m_Size; heap tree node navigation #region heap tree node navigation internal static Int32 PARENT(Int32 i) ... { return (i - 1 ) / 2 ; } internal static Int32 LEFT(Int32 i) ... { return 2 * i + 1 ; } internal static Int32 RIGHT(Int32 i) ... { return ( 2 * i + 2 ); } #endregion public Int32 Size ... { get ... { return m_Size; } } public MaxHeap(Int32 size) ... { m_Array = new Int32[size]; m_Size = Size; BuildMaxHeap(); } public MaxHeap(Int32[] inputArray) ... { if (inputArray == null ) throw new ArgumentNullException( " inputArray " , " The input Array cannot be null! " ); m_Array = inputArray; m_Size = inputArray.Length; BuildMaxHeap(); } public String Show() ... { // List the current heap elements return Common.ListTheArray(m_Array); } 6.2 Maintaining the heap property #region 6.2 Maintaining the heap property private void MaxHeapify(Int32 root) ... { if (root < 0 || root >= m_Array.Length) throw new ArgumentOutOfRangeException( " root " , root, " input root node out of range " ); Int32 heapSize = m_Size; Int32 left, right, largest; do ... { largest = root; left = LEFT(root); right = RIGHT(root); if (left < heapSize && m_Array[left] > m_Array[root]) largest = left; if (right < heapSize && m_Array[right] > m_Array[largest]) largest = right; if (largest != root) ... { Common.Exchange( ref m_Array[root], ref m_Array[largest]); root = largest; continue ; } else break ; } while (root < m_Size); } #endregion 6.3 Building a max heap #region 6.3 Building a max heap private void BuildMaxHeap() ... { for (Int32 i = m_Size / 2 - 1 ; i >= 0 ; i -- ) MaxHeapify(i); } #endregion Veriry a max heap #region Veriry a max heap public bool IsMaxHeap(Int32 root) ... { for (Int32 i = root; i < m_Size; i ++ ) ... { if (LEFT(i) < m_Size && m_Array[LEFT(i)] > m_Array[i]) return false ; if (RIGHT(i) < m_Size && m_Array[RIGHT(i)] > m_Array[i]) return false ; } return true ; } #endregion 6.4 The heapsort algorithm(Sort to non-increasing order) #region 6.4 The heapsort algorithm(Sort to non-increasing order) /**/ /// <summary> /// The heapsort algorithm(Sort to non-increasing order) /// </summary> public void Sort() ... { BuildMaxHeap(); for (Int32 i = m_Array.Length - 1 ; i > 0 ; i -- ) ... { Common.Exchange( ref m_Array[ 0 ], ref m_Array[i]); m_Size -- ; MaxHeapify( 0 ); } m_Size = m_Array.Length; } #endregion 6.5 Priority queues #region 6.5 Priority queues public Int32 Maximum() ... { return m_Array[ 0 ]; } public Int32 ExtractMax() ... { if (m_Size < 1 ) throw new ApplicationException( " heap underflow! " ); Int32 max = m_Array[ 0 ]; m_Array[ 0 ] = m_Array[(m_Size -- ) - 1 ]; MaxHeapify( 0 ); return max; } public void IncreaseKey(Int32 Index, Int32 Key) ... { if (m_Array[Index] > Key) throw new ArgumentException( " new key is smaller than current key " , " Key, Index " ); m_Array[Index] = Key; while (Index > 0 && m_Array[PARENT (Index)] < m_Array[Index]) ... { Common.Exchange ( ref m_Array[Index], ref m_Array[PARENT (Index)]); Index = PARENT (Index); } } /**/ /// <summary> /// Inserts the element Key into the heap /// </summary> /// <param name="Key"></param> public void Insert(Int32 Key) ... { if ( m_Size ++ > m_Array.Length) ... { Int32[] newLocationArray = new Int32[m_Array.Length * 2 ]; m_Array.CopyTo(newLocationArray, 0 ); m_Array = newLocationArray; } m_Array[m_Size - 1 ] = Int32.MinValue; IncreaseKey(m_Size - 1 , Key); } // The operation HEAP-DELETE(A, i) deletes the item in node i from heap A. public void Delete(Int32 Index) ... { if (Index < 0 || Index >= m_Size) throw new ArgumentOutOfRangeException( " Index " , Index, " Input wrong index! " ); Common.Exchange( ref m_Array[Index], ref m_Array[m_Size - 1 ]); m_Size -- ; if (Index >= m_Size) return ; Int32 Key = m_Array[Index]; if (Key > m_Array[PARENT(Index)]) while (Index > 0 && Key > m_Array[PARENT(Index)]) ... { Common.Exchange( ref m_Array[Index], ref m_Array[PARENT(Index)]); Index = PARENT(Index); } else MaxHeapify(Index); } #endregion } } }