栈的特点
- 先进后出(FILO)或者 后进先出(LIFO)
- 增删元素皆是在栈顶操作
- 一次只能删除一个数据项:当前栈顶元素
- 只允许访问一个数据项:当前栈顶元素
所需条件
- 一个链结点类Link,里面包含了需要存储的数据data和一个Link类型的引用变量next
- 一个封装了链表操作元素的行为类MyLinkList,里面包含了一个Link类型的引用变量first和若干个方法
分析实现
确定栈具有的功能:入栈push()、出栈pop()、查看栈顶元素getTop()、判空isEmpty()、判长length()、清空clear()
代码实现
1. Link类
1 public class Link { 2 3 public Object data; 4 public Link next; 5 6 public Link(Object data) { 7 this.data = data; 8 this.next = null; 9 } 10 11 public void displayLink() { 12 System.out.print(data + " "); 13 } 14 }
2. MyLinkList类
1 public class MyListList { 2 3 private Link first; 4 5 /** 6 * 判断链表是否为空 7 * @return 8 */ 9 public boolean isEmpty() { 10 return (first == null); 11 } 12 13 /** 14 * 在头结点处插入元素 15 * @param data 16 */ 17 public void insertFirst(Object data) { 18 Link newLink = new Link(data); 19 newLink.next = first; 20 first = newLink; 21 } 22 23 /** 24 * 删除头结点 25 * @return 26 */ 27 public Object deleteFirst() { 28 if (isEmpty()) { 29 return null; 30 } 31 Link temp = first; 32 first = first.next; 33 return temp.data; 34 } 35 36 /** 37 * 获得头结点存储的数据 38 * @return 39 */ 40 public Object getFirstData() { 41 return first.data; 42 } 43 44 /** 45 * 获得链表的长度 46 * @return 47 */ 48 public int length() { 49 Link current = first; 50 int count = 0; 51 while (current != null) { 52 count++; 53 current = current.next; 54 } 55 return count; 56 } 57 58 /** 59 * 清空链表 60 */ 61 public void clearList() { 62 Link current = first; 63 while (current != null) { 64 deleteFirst(); 65 current = current.next; 66 } 67 } 68 }
3. 链栈类
1 public class LinkStack { 2 3 private MyListList myListList; 4 5 public LinkStack() { 6 this.myListList = new MyListList(); 7 } 8 9 public boolean isEmpty(){ 10 return myListList.isEmpty(); 11 } 12 13 public void push(Object data) { 14 myListList.insertFirst(data); 15 } 16 17 public Object pop() { 18 return myListList.deleteFirst(); 19 } 20 21 public void clear() { 22 myListList.clearList(); 23 } 24 25 public int length() { 26 return myListList.length(); 27 } 28 29 public Object getTop() { 30 return myListList.getFirstData(); 31 } 32 }
4. 测试
1 public class LinkStackTest { 2 3 public static void main(String[] args) { 4 5 LinkStack linkStack = new LinkStack(); 6 7 System.out.println( "栈是否为空? " + linkStack.isEmpty()); 8 9 linkStack.push(10); 10 linkStack.push(20); 11 linkStack.push(30); 12 linkStack.push(0); 13 14 System.out.println("栈长: " + linkStack.length()); 15 16 System.out.println("栈顶元素: " + linkStack.getTop()); 17 18 // 清空栈 19 linkStack.clear(); 20 21 System.out.println( "栈是否为空? " + linkStack.isEmpty()); 22 23 linkStack.push(2); 24 linkStack.push(1); 25 linkStack.push(6); 26 linkStack.push(3); 27 linkStack.push(5); 28 // 取出栈元素,并打印 29 while(!linkStack.isEmpty()){ 30 Object pop = linkStack.pop(); 31 System.out.print(pop + " "); 32 } 33 System.out.println(); 34 } 35 }
5. 结果
栈是否为空? true 栈长: 4 栈顶元素: 0 栈是否为空? true 5 3 6 1 2
总结
- 使用链表作为底层实现,可以任意扩容,这一点比用数组实现好太多;
- 插入、查找、删除所需时间都是O(1),因为都是对栈顶元素操作。
对比链接:使用数组实现栈