Stack Intro
Stack作为一种基本的数据结构,用于存储对象集合。
对Stack的常用操作:
- 插入对象 ;
- 移除对象;(LIFO原则-last in first out)
- 遍历 ;
- 测试是否为空集 ;
根据以上操作类型,以String对象类型为例,编写API如下:
public class StackOfStrings | Comment |
---|---|
StackOfStrings() | create an empty stack |
void push(String item) | insert a new String onto the stack |
String pop() | remove and return the string most recently added |
boolean isEmpty() | is the stack empty? |
Stack - Linked-List Implementation
Linked-List Review
A linked list is a recursive data structure that is either empty(null) or a reference to a node have a generic item and a reference to a linked list.
这种递归的数据结构初次接触时打破了一些固有的思维方式。
private class Node { // a nested class
Item item; // a placeholder; generic mechanism-represent any reference type
Node next; // characterizes the linked nature
//no methods in this class
}
Build a linked list
Node first = new Node();
first.item = "itemOne";
Node second = new Node();
second.item = "itemTwo";
first.next = second;
...
Insert at the beginning
Node oldFirst = first; // save a link to the list
first = new Node(); // create a new node for the beginning
// set the instance variable in the new node
first.item = "insertHere";
first.next = oldFirst;
...
Remove from the beginning
first = first.next;
...
那个被移除掉的对象在这里成了“孤儿”,之后java的memory management system会回收这个对象之前占用的内存。
Traversal
for(Node x = first; x != null; x = x.next)
... //process x.item
...
Stack: Linked-List Representation
实现关键点:
- 维护一个指针指向链表里的第一个节点
- 从最前面插入对象/移除对象
关键代码:
public class LinkedStackOfStrings {
private class Node{
Item item;
Node next;
}
private Node first = null;
public void push(String item) {
Node oldFirst = first;
first = new Node();
first.item = item;
first.next = oldFirst;
}
public String pop() {
String item = first.item;
first = first.next();
return item;
}
public boolean isEmpty(){
return first == null;
}
}
Stack: Linked-List Performance
链表实现不用写循环。
构建一个innner class所需的内存:
Per Stack Node | Total: 40 bytes |
---|---|
Object Overhead | 16 bytes |
Extra Overhead | 8 bytes |
item | 8 bytes |
next | 8 bytes |
如果这个链表有N个对象,则需使用40N bytes
Stack - Array Implementation
思路:
- 使用一个数组 s[ ] 来存储stack上的N个对象 ;
- push: 在s[N]处插入新对象
- pop: 从s[N-1]处移除对象
问题:
- 创建数组时需要定义数组大小,但实际情况却是,往往无法事先知晓N
关键点:
- 数组大小的动态缩放
关键代码:
public class ArrayStackOfStrings{
private String[] s;
private int N = 0;
public ArrayStackOfStrings(){
s = new String[1]; // initialization
}
private void resize(int capacity) {
String[] copy = new String[capacity];
for(int i = 0; i < N; i++)
copy[i] = s[i];
s = copy;
}
public void push(String item) {
// if array is full, create a new array of twice the size and copy items
if(N == s.length) resize(2 * s.length);
// add the new item at s[N]; use N to index into array then increment N
s[N++] = item;
}
public String pop() {
String item = s[--N]; // remove item from s[N-1]; firstly decrement N, then use it to index into array
s[N] = null;// to avoid loitering; garbage collector claim memory only if no outstanding reference
// halve size of s[] when array is one-quarter full
if(N > 0 && N == s.length/4)
resize (s.length/2);
return item;
}
public boolean isEmpty() {
return N == 0;
}
}