While the assignment its self wasn't too hard, it took me a while to do all the conditional logic behind the Sink() function.
Here is my code:
using System; using System.Collections; using System.Collections.Generic; namespace Assignment9 { class MaxHeap<T> : IEnumerable<T> where T : IComparable { private T[] UnderlyingArray; private int ElementCount = 0; private int OldCount = 0; private bool IsHeap = true; public MaxHeap(int starting_size) { UnderlyingArray = new T[starting_size]; } public MaxHeap() { UnderlyingArray = new T[5]; } public int Count { get { return ElementCount; } } public void Clear() { UnderlyingArray = new T[UnderlyingArray.Length]; } public T this[int index] { get { return UnderlyingArray[index]; } } public void Add(T new_value) { if (!IsHeap) BuildHeap(); if (ElementCount == UnderlyingArray.Length) Resize(); UnderlyingArray[ElementCount] = new_value; Swim(); ElementCount++; } public T PopTop() { if (!IsHeap) BuildHeap(); T max = UnderlyingArray[0]; Swap(0, ElementCount - 1); UnderlyingArray[ElementCount - 1] = default(T); ElementCount--; Sink(); return max; } public void Sort() { if (!IsHeap) BuildHeap(); OldCount = ElementCount; for (int i = 0; i < OldCount; i++) { Swap(0, ElementCount - 1); ElementCount--; Sink(); } IsHeap = false; ElementCount = OldCount; } public void BuildHeap() { if (IsHeap) return; int last_item = OldCount - 1; for (int index = 0; index < OldCount / 2; index++) { Swap(index, last_item); last_item--; } ElementCount = OldCount; IsHeap = true; } private void Swim() { int current_index = ElementCount; while (current_index != 0) { int parent_index = FindParent(current_index); if (UnderlyingArray[current_index].CompareTo(UnderlyingArray[parent_index]) == 0) break; else if (UnderlyingArray[current_index].CompareTo(UnderlyingArray[parent_index]) > 0) Swap(current_index, parent_index); current_index = parent_index; } } private void Swap(int first, int second) { T temp = UnderlyingArray[first]; UnderlyingArray[first] = UnderlyingArray[second]; UnderlyingArray[second] = temp; } private void Sink() { int current_index = 0; while (current_index < ElementCount) { int max_child_index = current_index; int left_child_index = FindLeft(current_index); int right_child_index = FindRight(current_index); if (left_child_index >= ElementCount) break; if (right_child_index >= ElementCount) max_child_index = left_child_index; if (right_child_index < ElementCount && UnderlyingArray[left_child_index].CompareTo(UnderlyingArray[right_child_index]) == 0) max_child_index = left_child_index; if (right_child_index < ElementCount && UnderlyingArray[left_child_index].CompareTo(UnderlyingArray[right_child_index]) > 0) max_child_index = left_child_index; if (right_child_index < ElementCount && UnderlyingArray[left_child_index].CompareTo(UnderlyingArray[right_child_index]) < 0) max_child_index = right_child_index; if (UnderlyingArray[max_child_index].CompareTo(UnderlyingArray[current_index]) == 0) break; if (UnderlyingArray[max_child_index].CompareTo(UnderlyingArray[current_index]) > 0) Swap(current_index, max_child_index); current_index = max_child_index; } } private int FindParent(int current_index) { return (current_index - 1) / 2; } private int FindLeft(int current_index) { return (current_index * 2) + 1; } private int FindRight(int current_index) { return (current_index * 2) + 2; } private void Resize() { T[] new_array = new T[UnderlyingArray.Length * 2]; for (int index = 0; index < UnderlyingArray.Length; index++) new_array[index] = UnderlyingArray[index]; UnderlyingArray = new_array; } public IEnumerator<T> GetEnumerator() { for (int index = 0; index < ElementCount; index++) { T temp = UnderlyingArray[index]; //Console.WriteLine("Current Value: {0}", temp); yield return temp; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }
That's all for now, thanks for reading!
No comments:
Post a Comment