面试准备 - 最大堆的Csharp实现

面试中最常见的问题之一。。。在N个数中间寻找前K大个元素

最常见的解法就是最大堆 时间复杂度O(N*log(K)) 空间复杂度O(k)

实现了一个最简单的最大堆,每次有元素进来都和堆顶元素比较一下,如果新元素比较大就替换,然后就逐级更新到堆底

 

namespace Clover.Algoritms.DataStructure
{
    using System;
    using System.ComponentModel;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Threading;

    using Clover.Algoritms.Common;

    public class MaxHeap
    {
        public double[] items;

        public int count = 0;

        public MaxHeap(int capacity)
        {
            if (capacity <= 0)
            {
                throw new ArgumentOutOfRangeException("capacity");
            }
            this.items = new double[capacity];
            for (int i = 0; i < this.items.Length; i++)
            {
                this.items[i] = double.MinValue;
            }
        }

        public bool Validate()
        {
            for (int i = 0; i < this.items.Length; i++)
            {
                int left = 2 * i + 1;
                int right = 2 * i + 2;
                if (left < this.items.Length)
                {
                    if (this.items[left] > this.items[i])
                    {
                        return false;
                    }
                }
                if (right < this.items.Length)
                {
                    if (this.items[right] > this.items[i])
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public void MaxHeapify(int i, int size = -1)
        {
            var s = size > 0 ? size : items.Length;
            if (i >= s)
            {
                return;
            }

            var l = this.left(i);
            var r = this.right(i);
            var largest = i;
            if (l < s && items[l] > items[i])
            {
                largest = l;
            }
            if (r < s && items[r] > items[largest])
            {
                largest = r;
            }
            if (largest != i)
            {
                var temp = items[i];
                items[i] = items[largest];
                items[largest] = temp;
                MaxHeapify(largest);
            }
        }

        public void BuildMaxHeap()
        {
            for (int i = items.Length / 2; i >= 0; i--)
            {
                this.MaxHeapify(i);
            }
        }

        public int left(int i)
        {
            return i * 2 + 1;
        }

        public int right(int i)
        {
            return i * 2 + 2;
        }

        public int parent(int i)
        {
            return i / 2 - 1;
        }

        public void HeapSort()
        {
            this.BuildMaxHeap();
            for (int i = items.Length / 2; i >= 1; i--)
            {
                var temp = items[0];
                items[0] = items[i];
                items[i] = temp;
                var size = items.Length - 1 - items.Length / 2 + i;
                this.MaxHeapify(i, size);
            }
        }

        //max heap is used to find top k smallest items.
        public void PickTopN(double d)
        {
            if (count < items.Length)
            {
                items[count] = d;
                count++;
                if (count >= items.Length)
                {
                    this.BuildMaxHeap();
                }
            }
            else if (d < items[0])
            {
                items[0] = d;
                this.MaxHeapify(0);
            }
        }

        public double Maximun()
        {
            if (count == 0)
            {
                throw new Exception("there is no any element in heap");
            }

            return items[0];
        }

        public double HeapExtractMax()
        {
            if (count == 0)
            {
                throw new Exception("there is no any element in heap");
            }
            var max = items[0];
            items[0] = items[count];
            count--;
            this.MaxHeapify(0);
            return max;
        }

        public void MaxHeapInsnsert(double d)
        {
            count++;
            double[] newItems = new double[count];
            for (int i = 0; i < count - 1; i++)
            {
                newItems[i] = items[i];
            }
            newItems[count - 1] = double.MinValue;
            items = newItems;
            MaxHeapIncreaseKey(count - 1, d);
        }

        private void MaxHeapIncreaseKey(int ind, double d)
        {
            var i = ind;
            if (d < items[i])
            {
                throw new Exception("new key is smaller than than current key");
            }
            items[i] = d;
            while (i > 0 && items[this.parent(i)] < items[i])
            {
                ObjectExtension.Exhange(ref items[i], ref items[this.parent(i)]);
                i = this.parent(i);
            }
        }
    }
}

 

posted on 2014-02-21 08:27  听说读写  阅读(2094)  评论(0编辑  收藏  举报

导航