數據結構中的堆

一:堆排序

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


    }
}
相關文章
相關標籤/搜索