基于最小二叉堆的优先级队列-C#实现,以此为基础的K路合并排序算法

原创 2007年10月05日 18:03:00
 
这两个程序实际上就是 算法导论6.5-3和6.5-8的C#实现。在Visual C# 2005下测试通过

  186 public class MinHeap

  187 {

  188     #region Private status

  189     private Int32[] m_Array;

  190     private Int32 m_Size;

  191 

  192     public Int32 Size { get { return m_Size; } }

  193     #endregion

  194 

  195     #region heap tree node navigation

  196     internal static Int32 PARENT(Int32 i) { return (i - 1) / 2; }

  197     internal static Int32 LEFT(Int32 i) { return 2 * i + 1; }

  198     internal static Int32 RIGHT(Int32 i) { return (2 * i + 2); }

  199     #endregion

  200 

  201     #region ctor

  202     public MinHeap(Int32 size)

  203     {

  204         if (size < 512) size = 512;

  205         m_Array = new Int32[size];

  206         m_Size = 0;

  207     }

  208 

  209     public MinHeap(Int32[] inputArray)

  210     {

  211         if (inputArray == null)

  212             throw new ArgumentNullException("inputArray", "The input Array cannot be null!");

  213         m_Array = inputArray;

  214         m_Size = inputArray.Length;

  215 

  216         BuildMinHeap();

  217     }

  218     #endregion

  219 

  220     #region Build a min heap

  221     private void BuildMinHeap()

  222     {

  223         for (Int32 i = m_Size / 2 - 1; i >= 0; i--) MinHeapify(i);

  224     }

  225     #endregion

  226 

  227     #region Maintaining the minimal heap property

  228     private void MinHeapify(int root)

  229     {

  230         if (root < 0 || root >= m_Size)

  231             throw new ArgumentOutOfRangeException("root", root, "input root node out of range");

  232 

  233         Int32 heapSize = m_Size;

  234         Int32 left, right, least ;

  235 

  236         do

  237         {

  238             least = root;

  239             left = LEFT(root);

  240             right = RIGHT(root);

  241 

  242             if (left < heapSize && m_Array[left] < m_Array[root]) least = left;

  243             if (right < heapSize && m_Array[right] < m_Array[least]) least = right;

  244 

  245             if (least != root)

  246             {

  247                 Common.Exchange(ref m_Array[least], ref m_Array[root]);

  248                 root = least;

  249                 continue;

  250             }

  251             else

  252                 break;

  253         } while (root < heapSize);

  254     }

  255     #endregion

  256 

  257     #region min-priority queue operations

  258     public Int32 Minium {

  259         get {

  260             if (m_Size < 1) throw new ApplicationException("Heap is empty now!");

  261             return m_Array[0];

  262         }

  263     }

  264 

  265     public Int32 ExtractMin()

  266     {

  267         if (m_Size < 1) throw new ApplicationException("Heap is empty now!");

  268         else if (m_Size == 1) return m_Array[m_Size--];

  269 

  270         Int32 key = m_Array[0];

  271         m_Array[0] = m_Array[(m_Size--) - 1];

  272         MinHeapify(0);

  273 

  274         return key;

  275     }

  276 

  277     public void DecreaseKey(Int32 Index, Int32 Key)

  278     {

  279         if (Index < 0 || Index >= m_Size)

  280             throw new ArgumentOutOfRangeException("Index", Index, "input root node out of range");

  281         if (Key > m_Array[Index])

  282             throw new ArgumentException("Input value larger than specified element!", "value");

  283 

  284         Int32 parent = PARENT(Index);

  285         while (Index > 0)

  286         {

  287             if (m_Array[parent] > Key)

  288             {

  289                 Common.Exchange(ref m_Array[parent], ref m_Array[Index]);

  290                 Index = parent;

  291                 parent = PARENT(Index);

  292             }

  293             else

  294                 break;

  295         }

  296 

  297         m_Array[Index] = Key;

  298     }

  299 

  300     public void Insert(Int32 Key)

  301     {

  302         // Relocate the storage

  303         if (++m_Size > m_Array.Length)

  304         {

  305             Int32[] newLocationArray = new Int32[m_Array.Length * 2];

  306             m_Array.CopyTo(newLocationArray, 0);

  307             m_Array = newLocationArray;

  308         }

  309 

  310         m_Array[m_Size - 1] = Int32.MaxValue;

  311         DecreaseKey(m_Size - 1, Key);

  312     }

  313     #endregion

  314 

  315     #region Verify the MinHeap

  316     public Boolean MinHeapVerify()

  317     {

  318         for(Int32 i =0; i < m_Size; i++)

  319         {

  320             if (LEFT(i) < m_Size && m_Array[LEFT(i)] < m_Array[i]) return false;

  321             if (RIGHT(i) < m_Size && m_Array[RIGHT(i)] < m_Array[i]) return false;

  322         }

  323         return true;

  324     }

  325     #endregion

  326 

  327     #region  List the current heap elements

  328     public String Show()

  329     {

  330         // List the current heap elements

  331         return Common.ListTheArray(m_Array, m_Size);

  332     }

  333     #endregion

  334 }



Give an O(n lg k)-time algorithm to merge k sorted lists into one sorted list, where n is the total number of elements in all the input lists. (Hint: Use a min-heap for k-way merging.)

public static Int32[] KWayMergeSort(List<Int32[]> InputArrays, Int32 TotalLength)
...{
    Int32 k 
= InputArrays.Count;

    Int32[] output 
= new Int32[TotalLength];
    Int32 outIdx 
= 0;
    Int32[] indice 
= new Int32[k]; //记录各个数组的当前位置
    MinHeap heap = new MinHeap(k); //用于排序以及提取最小值的堆

    
for (Int32 i = 0; i < k; i++) heap.Insert((InputArrays[i])[indice[i]++]);  //插入每个数组的首元素

    Boolean elementLeft 
= true;  //记录当前所有数组中是否还有剩余的元素
    Int32 leastIdx = 0;    
    
do
    
...{
        output[outIdx
++= heap.ExtractMin();  //插入当前的剩余堆中和数组中的最小元素

        elementLeft 
= false;  
    
// 在以下循环中提取首个还有剩余元素的数组的索引,并且判断是否还有剩余的待插入的元素
        for (Int32 i = 0; i < k; i++)
        
...{
            
if (indice[i] < InputArrays[i].Length)
            
...{
                leastIdx 
= i;
                elementLeft 
= true;
                
break;
            }

        }


        
if (!elementLeft) break;
        
        
for (Int32 i = leastIdx + 1; i < k; i++)
            
if (indice[i] + 1 < InputArrays[i].Length && InputArrays[i][indice[i]] < InputArrays[leastIdx][indice[leastIdx]])
                leastIdx 
= i; //取得剩余数组中最小元素所在的数组的索引
 
        heap.Insert(InputArrays[leastIdx][indice[leastIdx]
++]);  //插入剩余数组中的最小元素
    }
 while (elementLeft);

    
while (heap.Size > 0) output[outIdx++= heap.ExtractMin();   //依次插入堆中剩余的元素

    
return output;
}

C#实现优先队列 基于二叉堆 附使用案例

前言 想用下C#的优先队列,结果发现居然没有,简直蛋疼。。。 感谢 http://www.cnblogs.com/skyivben/archive/2009/04/18/1438731.html 博主...

手工实现堆(最小堆)

做ACM班作业时候数据结构有一题要用优先数列,明显不会,看来网上的都是用C++的STL封装函数做的,作为一个有理想的人,怎么能在不知道原理的情况下直接套用呢?所以我去看了一下优先数列,发现又跟堆这个概...

最小优先级队列(基于最小二叉堆算法)

在最小生成树Prim算法中,可以利用最小优先级队列来改善时间复杂度,同时在单源最短路径Dijkstra算法中也同样可以利用这种最小优先级队列来改善算法时间复杂度。实现最小优先级队列可以有很多种方式,比...

算法基础:排序(四)——二叉堆、优先队列、堆排序——Python实现

1. 堆 Heap堆是利用完全二叉树的结构来维护数据的一种的数据结构,因此堆也叫做二叉堆。借助下面这张图可以直观的理解二叉堆的结构和特点: 大家不难发现,元素的标号与其父节点的标号n的关系为: 左...

分治法合并排序算法实现merge

  • 2013年11月03日 23:28
  • 200KB
  • 下载

最小二叉堆代码(基于一整形数组实现)

看了一下午。。。根据算法导论上的伪代码写的。 #include using namespace std; int A[11]={0,4,1,3,2,16,9,10,14,8,7}; in...
  • ThinkPP
  • ThinkPP
  • 2011年08月24日 21:02
  • 171

[数据结构] 二叉堆,堆排序,优先级队列

前言最近在看算法导论中的第六章堆排序,忍不信手又痒了起来,利用零散时间,参照书里的思路,利用java实现了一些堆的基本操作,供小白参考。有时间会整理堆的介绍和一些性质,这事后话。我也是菜鸟一个,代码中...

合并排序算法

  • 2012年07月07日 15:35
  • 981B
  • 下载

合并排序算法

  • 2012年12月04日 09:07
  • 25KB
  • 下载

合并排序算法介绍,以及C语言实现

算法介绍 C语言实现 算法介绍合并排序算法原理简单,时间复杂度低,且算法具有稳定性,在各类排序算法中具有较好的性能。本文将介绍合并算法的原理,并给出其C语言的实现。合并排序将待排序数组分隔成两个部分。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于最小二叉堆的优先级队列-C#实现,以此为基础的K路合并排序算法
举报原因:
原因补充:

(最多只允许输入30个字)