调整数组大小

选择用数组表示栈内容意味着用例必须预先估计栈的最大容量。在 Java 中,栈一旦创建,其大小是无法改变的,因此栈使用的空间只能是这个最大容量的一部分。选择大容量的用例在栈为空或几乎为空时会浪费大量的内存。因此,我们修改了数组的实现,动态调整数组 a[] 的大小,使得它既足以保存所有元素,又不至于浪费过多的空间。实际上,完成这些目标非常简单。首先实现一个方法将栈移动到另一个大小不同的数组中:

// 调整数组大小:实质上是创建了一个新的指定大小的数组,再将值赋入
private void resize(int max){ Item[] temp = (Item[])new Object[max];for(int i = 0; i < N; i++){temp[i] = a[i];}a = temp;
}

在 push() 中,检查数组是否太小。具体来说,我们会通过检查栈大小N和数组大小 a.length() 是否相等来检查数组是否能容纳新的元素。如果没有多余的空间,我们会将数组的长度加倍。然后就可以和从前一样用 a[N++] = item 插入新元素了。

public void push(Item item)
{   // 将元素添加到栈顶if(a.length == N){resize(2 * a.length); // 如果栈满了,则将栈扩容一倍,1->2.2->4,4->8}a[N++] = item;
}

类似,在 pop() 中,首先删除栈顶的元素,然后如果数组太大我们就将它的长度减半。稍加思考,你就明白正确的检测条件是栈大小是否小于数组的四分之一。在数组长度被减半后,它的状态约为半满,在下次需要改变数组大小之前仍然能够多次 push() 和 pop() 操作。

public Item pop()
{   // 从栈顶删除元素Item item = a[--N];a[N] = null; // 避免对象游离if (N > 0 && a.length/4 == N) // 如果栈的中的元素达到了栈的1/4,则将栈容量减半{resize(a.length/2);}
return item;
}

完整代码(包含迭代):

import java.util.Iterator;/*** 下压栈(能够动态调整数组大小的实现)*/public class ResizingArrayStack<Item> implements Iterable<Item> {private Item a[] = (Item[])new Object[1]; // 栈中元素private int N; // 栈中元素个数public boolean isEmpty(){return N == 0;} // 元素个数为0则栈空public int size(){return N;}private void resize(int max){Item[] temp = (Item[])new Object[max];for(int i = 0; i < N; i++){temp[i] = a[i];}a = temp;}public void push(Item item){   // 将元素添加到栈顶if(a.length == N) resize(a.length * 2); // 如果栈满了,则将栈扩容一倍,1->2.2->4,4->8a[N++] = item;}public Item pop(){   // 从栈顶删除元素Item item = a[--N];a[N] = null;if(N > 0 && a.length/4 == N) resize(a.length/2); // 如果栈的中的元素达到了栈的1/4,则将栈容量减半return item;}@Overridepublic Iterator<Item> iterator() {return new ReverseArrayIterator();}private class ReverseArrayIterator implements Iterator<Item>{   // 支持后进先出的迭代private int i = N;@Overridepublic boolean hasNext() {return i > 0;}@Overridepublic Item next() {return a[--i];}@Overridepublic void remove() {}}public static void main(String[] args) {ResizingArrayStack<String> stack = new ResizingArrayStack<>();stack.push("数据1");stack.push("数据2");stack.push("数据3");for (String s : stack) {System.out.println(s);}}
}

示例:

public static void main(String[] args) {ResizingArrayStack<String> stack = new ResizingArrayStack<>();stack.push("数据1");stack.push("数据2");stack.push("数据3");for (String s : stack) {System.out.println(s);}
}

运行效果:

数据3
数据2
数据1

这个算法是 Stack API 的一种能够动态改变数组大小的实现。用例能够创建任意类型数据的栈,并支持用例用 foreach 语句按照后进先出的顺序迭代访问所有栈元素。这个实现的基础是 Java 的语言特性,包括 Iterable 和 Iterator。具体可以看《Algorithms》Java 语言特性。

这份泛型的可迭代的 Stack API 的实现是所有集合类抽象类型实现的模板。它将所有元素保存在数组中,并动态调整数组的大小以保持数组大小和栈之比小于一个常数。

《Algorithms》—— 下压(LIFO)栈(能够动态调整数组大小的实现)相关推荐

  1. vba动态二维数组_VBA实战技巧05: 动态调整数组以存储所需数据

    学习Excel技术,关注微信公众号: excelperfect 数组是一种常用的数据结构,可用来存储一组相同类型的数据,你可以将一个数组变量视为一个迷你的电子表格,通过引用数组中的位置来存储或者获取数 ...

  2. linux sd卡 分区变大,Linux 动态调整分区大小

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? Ubuntu根分区空间告急,即将使用完毕 先清理出一定空间 移除不再需要的软件包1sudo apt autoremove ...

  3. Unity 窗口制作 调整窗口大小 动态调整UI大小 窗口拖拽 UI拖拽

    Unity 简易窗口: 首先咱们看一下是不是自己想要的效果 组件可调整参数: 下面是同比例缩放的调整效果,如果只是缩放这个窗口里面的内容,这个是个不错的选择 资源链接: 下载地址.

  4. 动态调整div大小 html,如何动态的根据用户屏幕的分辨率改变div的大小?

    我想设计一个 app 产品主页,主页分 3 屏,要求网页会根据用户设备的分辨率自动调整每一屏的大小,例如我现在的 1366*768 则每屏显示 1366*768:如果另外有用户的分辨率是 1280*7 ...

  5. HTML如何设置幻灯片大小和位置,javascript – 动态调整skitter幻灯片图像大小

    如何将幻灯片图像调整(缩放)到 jquery或css或其他任何方式的不同大小? 它总是加载主图像的全宽和高度,并用以下方式控制不起作用. 可以通过以下示例代码调整图像滑块容器的大小,但如果图像大于53 ...

  6. Java笔记整理五(Iterator接口,泛型,常见数据结构(栈,队列,数组,链表,红黑树,集合),jdk新特性,异常,多线程,Lambda表达式)

    Java笔记整理五 1.1Iterator接口 Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象 ...

  7. 分布式作业 Elastic Job 如何动态调整

    转载自   分布式作业 Elastic Job 如何动态调整 前面分享了两篇分布式作业调度框架 Elastic Job 的介绍及应用实战. ElasticJob-分布式作业调度神器 分布式作业 Ela ...

  8. java动态扩展_java栈内存动态扩展要怎么理解?要如何实现?

    小伙伴们知道如何在java栈中内存动态扩展吗?这是虚拟机中的一个概念,下面让我们一起来看看该如何实现吧. 一.内存概念 在java中,我们一般会简单把java内存区域划为两种:堆内存与栈内存.其实这种 ...

  9. 《恋上数据结构第1季》动态扩容数组原理及实现

    动态扩容数组 什么是数据结构? 线性表 数组(Array) 动态数组(Dynamic Array) 动态数组接口设计 清除所有元素 - clear() 添加元素 - add(E element).ad ...

最新文章

  1. 如何查看SharePoint未知错误
  2. 前标识(NT AUTHORITY\NETWORK SERVICE)没有对 (转)
  3. 原生JS字符串操作方法汇总
  4. 学术造假?撤销职称!不端“黑历史”将影响未来评审
  5. linux下keytool生成证书_生成证书命令keytool
  6. python为list实现find方法
  7. IntelliJ IDEA 2019.3 正式发布,给我们带来哪些新特性?| CSDN 博文精选
  8. Windows Server 2008 R2忘记管理员密码后的解决方法
  9. 【EOS】2.3 深入理解ABI文件
  10. 使用Cmder替换cmd,让你的开发飞起来
  11. 51nod1394 差和问题 值域线段树
  12. vs201检查更新不成功_Kubernetes玩转Pod滚动更新123
  13. 190610每日一句,如果你想变得更加强大,你该问问自己这个问题;失败造就了成功
  14. Live2D和wallpaperEngine公用
  15. easyar 实现模型的旋转和缩放
  16. Task5 | CFA (Amos+Mplus) | 五因素心智觉知度量表:正念是什么?
  17. 如何才是一名优秀的好员工
  18. word恢复默认样式
  19. Filter Control for Visual Studio LightSwitch 本地化处理
  20. excel打开提示不适合这台计算机,《win10提示excle安装》 win10 :Excel文件打不开、显示“此应用无法在你的电脑上运行”怎么办?...

热门文章

  1. 能在市场上大概率赚钱的人类型
  2. 既然光纤那么快,为什么路由器和电脑之间不用光纤连接,而还用普通网线?
  3. 买手机需要128 G的存储空间吗?
  4. timerfd_create Function not implemented问题
  5. SQL Server FILESTREAM查询和文件组
  6. sql子句的执行顺序_SQL Server查询执行计划– WHERE子句的示例
  7. 一门从业4年都没能用上的优化技术
  8. 荣耀A55高调上市仅仅为孤独求败?
  9. C++静态库与动态库(转)
  10. 【备份】信工apache中有关http.conf的虚拟目录相关配置参考