通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

C++、java都将线程共享的变量等放到堆内存中,为什么选择堆这种数据结构

因为执行堆排序所需的时间呈对数增长,而其他算法可能随着要排序的元素数量的增加而呈指数级增长。这种排序算法非常有效。它比其他同样有效的排序算法更容易理解。

一、C++、java为什么选择堆这种数据结构

效率:执行堆排序所需的时间呈对数增长,而其他算法可能随着要排序的元素数量的增加而呈指数级增长。这种排序算法非常有效。

内存使用: 内存使用是最小的,因为除了保存要排序的元素的初始列表所必需的东西之外,它不需要额外的内存空间来工作

简单性: 它比其他同样有效的排序算法更容易理解,因为它不使用先进的计算机科学概念,如递归。

堆排序(HeapSort)基本概念

堆排序是一种基于二叉堆(binary heap)数据结构的基于比较的排序技术。它类似于选择排序,先找到最小的元素,然后把最小的元素放在最开始, 然后对其余元素重复相同的过程。

堆的介绍详见数据结构–Heap介绍及Java代码的实现示例

由于二叉堆是一棵完整的二叉树,所以它可以很容易地表示为数组,而基于数组的表示方式非常节省空间。如果父节点存储在索引I,左边的子节点可以用2 * I + 1计算,右边的子节点可以用2 * I + 2计算(假设索引从0开始)。

堆排序是一种in-place算法,排序后,相同的元素无法保证相对的顺序,即是不稳定的。

延伸阅读:

二、堆和栈的不同

1、分配方式不同:

栈: 由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间

堆: 需要程序员自己申请,并指明大小,在c中malloc函数

如p1 = (char *)malloc(10);

在C++中用new运算符

如p2 = (char *)new(10);

但是注意p1、p2本身是在栈中的。

2、空间大小不同:

一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M。

3、分配效率不同:

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执 行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考 数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的 内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

4、碎片问题:

栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,

会遍历该链表,寻找名列前茅个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块 内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的 大小,系统会自动的将多余的那部分重新放入空闲链表中。

对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。

5、生长方向:

对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用较广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。

相关文章