博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

让人迷惑的堆(Heap)

Posted on 2011-01-17 01:20  肖敏  阅读(669)  评论(0编辑  收藏  举报

      在很多中文的教科书中,经常把栈(Stack)叫成堆栈。实际上栈Stack和堆Heap是完全不同的概念。我们经常听说的堆栈溢出,其实是指栈溢出Stack Overflow,而实际上堆也会溢出Heap Overflow。

     Stack和Heap本身是一对近义词,做动词时,都表示“堆放” 。而区别在于Stack的意思表示“堆成一摞"(stack your books up on the shelves)而Heap表示”堆成一堆“(heap firewood around the fireplace)。直观来看Stack应该是个线型,而Heap则是个树形或三角型。因此台湾把Stack翻译成”堆叠“应该更好一些。

     现在我们所知道的堆的概念,主要有两个地方经常用到:

     a) 数据结构中:堆表示经过排序的树结构。实际上”堆“ 这个概念最初就是在堆排序中提出的。(《算法导论》第七章 堆排序)后来堆这种结构也被用于

     b) 动态内存分配中:才有了我们现在经常说的”堆“的概念。比如说托管堆,C语言中的堆。但是我们知道,不管是.Net中的托管堆还是C语言中的堆,他们的结构并不是树型结构,这就对我们理解造成了一定的困扰。这是因为用的已经不是它的字面意思了。

     我有个同事说到,他来公司时被问及Stack跟Heap的区别。这个题目很迷惑。

     从历史源头来说,Stack的概念最早由德国人弗里德里希·鲍尔(Friedrich Ludwig Bauer)在20世纪50年代提出,当时是用于解决命题表达式的演算问题。并因此获得得了计算机先驱奖。而后,巴登(Robert Barton)才将堆栈用做存储结构用于解决Algol语言中函数递归调用的问题。而Heap的概念是罗伯特·弗洛伊德由(Robert W.Floyd)和威廉姆斯(J.Williams)在1964年共同发明了著名的堆排序算法( Heap Sort )中引入的。

     从数据结构的角度来说,Stack是先入后出的线性结构,而堆是排序过的树形结构。从存储分配释放的规则角度来说,Stack是后分配先释放的一种内存区域,而堆则是任意分配(没有先后顺序)的内存区域。而现在大部分提到"堆"的概念时,往往指的是后者。

     在《STACK & HEAP (栈和堆), 从C\JAVA\系统三个角度看其区别-TECH-摘录》中,摘录了不同背景下用到的"堆"的概念。一是c中的,二是对于java的,三是从os角度,尽管各有不同,但是有一点是不变的,那就是内存分配释放的原则是:不分先后顺序。至于是由程序分配释放(C/C++ runtime中可以由程序分配释放)还是由系统分配释放(java/.net),那都是堆。