码迷,mamicode.com
首页 > Windows程序 > 详细

C#实现范型二叉堆

时间:2015-07-23 19:30:57      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:

二叉堆结构解释: http://www.apkbus.com/android-58533-1-1.html

 

代码实现方式:

using System;
using System.Collections.Generic;

namespace BinaryHeap
{
    /// <summary>  
    /// 排序的枚举
    /// </summary>  
    public enum Order
    {
        ASC = 0,
        DESC = 1
    }

    /// <summary>  
    /// 二叉堆
    /// </summary>  
    /// <typeparam name="T">填入你需要存储的类型</typeparam>  
    public class BinaryHeap<T> where T : IComparable<T>
    {
        /// <summary>  
        /// The size of the heap  
        /// </summary>  
        public int Size { get; set; }

        private int length;
        /// <summary>  
        /// 堆的长度
        /// </summary>  
        public int Length
        {
            get
            {
                return length;
            }
            private set { length = value; }
        }

        private T[] Items { get; set; }
        private Order Order = Order.ASC;

        /// <summary>  
        /// The Cons of the heap  
        /// </summary>  
        /// <param name="size">The default size of the heap</param>  
        /// <param name="order">The order of the heap</param>  
        public BinaryHeap(int size, Order order)
        {
            if (size < 1)
            {
                throw new Exception("二叉堆最少长度2");
            }

            this.Size = size;
            this.Order = order;
            this.Size++;
            Items = new T[this.Size];
            this.length = 0;
        }


        /*
         我们可以举一个例子,假设我们已经有了一个最小二叉堆(其中有7个元素),现在我们要插入一个元素17到这个二叉堆中去,那么插入后二叉堆大小就会加一变成8
         10 30 20 34 38 30 24 17
        
         现在17位下划线的那个,我们已经将他放在数组的最后位置了,然后我们比较他与他的父节点(位置为8/2 = 4),在位置4(从1开始数)的为34,由于17小于34,所以我们交换彼此,得到下图:
         10 30 20 17 38 30 24 34
         
         现在17跑到位置4中去了,然后我们比较17和他的新的父节点(位置为4/2 = 2),
         在位置2(从1开始数)的为30,由于17还是小于30,所以交换彼此,得到下图:
         10 17 20 30 38 30 24 34
         现在17跑到第二位了,继续比较,父节点位置为2/2 = 1,由于17不小于10,所以这里就没有必要比较了,走到这一步我们的新元素17添加完成。现在的堆已经添加了元素17,堆中有8位按照最小二叉堆规则排序的元素。
         */

        /// <summary>  
        /// 添加节点
        /// </summary>  
        /// <param name="item"></param>  
        public void Add(T item)
        {
            if (this.length == 0)
            {
                Items[1] = item;
            }
            else
            {
                int len = this.length;
                if (len >= this.Size)
                {
                    throw new Exception("二叉堆已经满了,不能再添加了");
                }

                int endPos = len + 1;
                Items[endPos] = item;

                //从二叉堆最中间的数字 和 最末尾的数字第一次进行比较
                int parentPos = endPos / 2;
                bool isContinue = true;
                while (parentPos != 0 && isContinue)
                {
                    // 升序 
                    if (Order == BinaryHeap.Order.ASC)
                    {
                        //实例比参数小就返回 -1 
                        if (Items[endPos].CompareTo(Items[parentPos]) < 0)
                        {
                            //交换
                            Swap(ref Items[endPos], ref Items[parentPos]);

                            endPos = parentPos;
                            parentPos = endPos / 2;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else
                    {
                        //降序
                        if (Items[endPos].CompareTo(Items[parentPos]) > 0)
                        {
                            Swap(ref Items[endPos], ref Items[parentPos]);

                            endPos = parentPos;
                            parentPos = endPos / 2;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                }
            }

            
            this.length++;
        }

        /// <summary>  
        /// 删除节点
        /// </summary>  
        /// <returns>if the order is ASC, return the smallest one, if DESC, return the largest one.</returns>  
        public T Remove()
        {
            if (this.length == 0)
            {
                throw new Exception("二叉树为空");
            }
            // 把二叉堆的第一个元素删除掉 
            T removedItem = Items[1];
            int len = this.length;
            Items[1] = Items[len];      //把末尾的元素添加到第一位

            // 减少二叉堆的长度
            this.length--;

            //先计算出第一次比较的两个节点
            int currentPos = 1;
            int leftChildPos = currentPos * 2;                  
            int rightChildPos = currentPos * 2 + 1;

            bool isContinue = true;

            while ((leftChildPos <= len || rightChildPos <= len) && isContinue)
            {
                // Compare the removing item to its childrens, swap each other if needed  
                if (Order == BinaryHeap.Order.ASC)
                {
                    #region 升序
                    if (leftChildPos <= len && rightChildPos <= len)
                    {
                        //当左节点小于右节点的时候,当前节点就跟左节点对比(是否交换)
                        if (Items[leftChildPos].CompareTo(Items[rightChildPos]) < 0 && Items[currentPos].CompareTo(Items[leftChildPos]) >= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[leftChildPos]);
                            currentPos = leftChildPos;
                        }
                        //当左节点大于等于右节点的时候,当前节点就跟右节点对比(是否交换)
                        else if (Items[leftChildPos].CompareTo(Items[rightChildPos]) >= 0 && Items[currentPos].CompareTo(Items[rightChildPos]) >= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[rightChildPos]);
                            currentPos = rightChildPos;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else if (leftChildPos <= len)           //左节点比较
                    {
                        if (Items[currentPos].CompareTo(Items[leftChildPos]) >= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[leftChildPos]);
                            currentPos = leftChildPos;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else if (rightChildPos <= len)           //右节点比较
                    {
                        if (Items[currentPos].CompareTo(Items[rightChildPos]) >= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[rightChildPos]);
                            currentPos = rightChildPos;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else
                    {
                        isContinue = false;
                    }
                    #endregion

                    leftChildPos = currentPos * 2;
                    rightChildPos = currentPos * 2 + 1;
                }
                else
                {
                    #region 降序
                    if (leftChildPos <= len && rightChildPos <= len)
                    {
                        if (Items[leftChildPos].CompareTo(Items[rightChildPos]) > 0 && Items[currentPos].CompareTo(Items[leftChildPos]) <= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[leftChildPos]);
                            currentPos = leftChildPos;
                        }
                        else if (Items[leftChildPos].CompareTo(Items[rightChildPos]) <= 0 && Items[currentPos].CompareTo(Items[rightChildPos]) <= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[rightChildPos]);
                            currentPos = rightChildPos;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else if (leftChildPos <= len)
                    {
                        if (Items[currentPos].CompareTo(Items[leftChildPos]) <= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[leftChildPos]);
                            currentPos = leftChildPos;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else if (rightChildPos <= len)
                    {
                        if (Items[currentPos].CompareTo(Items[rightChildPos]) <= 0)
                        {
                            Swap(ref Items[currentPos], ref Items[rightChildPos]);
                            currentPos = rightChildPos;
                        }
                        else
                        {
                            isContinue = false;
                        }
                    }
                    else
                    {
                        isContinue = false;
                    }
                    #endregion

                    leftChildPos = currentPos * 2;
                    rightChildPos = currentPos * 2 + 1;
                }
            }

            return removedItem;
        }

        /// <summary>  
        /// 排序二叉堆
        /// </summary>  
        /// <returns>Return the sorted heap array</returns>  
        public IEnumerable<T> Sort()
        {
            if (this.length == 0)
            {
                throw new Exception("The heap is empty");
            }

            while (this.length > 0)
            {
                yield return Remove();
            }
        }

        #region Private method
        /// <summary>  
        /// Swap each other  
        /// </summary>  
        /// <param name="t1">The first one</param>  
        /// <param name="t2">The second one</param>  
        private void Swap(ref T t1, ref T t2)
        {
            T temp = t1;
            t1 = t2;
            t2 = temp;
        }
        #endregion
    }
}

C#实现范型二叉堆

标签:

原文地址:http://www.cnblogs.com/plateFace/p/4671259.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!