数据结构中的堆

一:堆排序

     堆排序(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;
        }


    }
}
posted @ 2016-09-12 22:41  jiuguang  阅读(1063)  评论(0编辑  收藏  举报