数据结构系列之栈
栈是一种常见的数据结构,它只能在一端进行数据的插入,移除操作。用于操作的这一段端通常叫做栈顶。栈因为只有一个操作端所以它的数据存取特点是先进后出。即先入栈的元素后出栈。实现栈有两种方式,一种是使用数组实现,一种是使用链表实现。下面是栈的简单示意图,以及出栈,入栈示意图:
数组实现
数组实现的栈,java已经实现了这样一种数据结构,就是Stack类,继承于vector。下面分析一下stack这个类:
public Stack()
public E push(E item)
public synchronized E pop()
public synchronized E peek()
public boolean empty()
public synchronized int search(Object o)
private static final long serialVersionUID = 1224463164541339165L;
可以看到stack类的内容很少,而且对于栈这种数据结构而言,重要的方法就3个。分别是入栈push(),出栈pop(),返回栈顶元素peek()。
Stack的push入栈方法(代码不贴了直接看图):
很简单,stack的push方法直接调用的是它父类vector的addElement方法,往数组中添加一个元素。
出栈pop方法:
pop出栈是删除数组里的最后一个元素。
peek方法,返回数组中的最后一个元素:
链表实现
先贴上实现代码,也只是实现了栈的 pus,pop ,peek这几个比较重要的方法。
public class LinkedStack {
public int size;
private Node head;
public LinkedStack() {
head = null;
}
/**
* 元素入栈(使用头插法)
*
* @param data
*/
public void push(String data) {
Node newNode = new Node(data);
if (isEmpty()) {
head = newNode;
} else {
newNode.next = head;
head = newNode;
}
size++;
}
/**
* 元素出栈(使用头删法)
*
* @return
*/
public String pop() {
if (isEmpty()) return null;
String s = head.data;
head = head.next;
size--;
return s;
}
/**
* 返回栈顶元素
*
* @return
*/
public String peek() {
if (isEmpty()) return null;
return head.data;
}
public boolean isEmpty() {
return size == 0;
}
public static class Node {
String data; //以String为例
Node next;
public Node(String data) {
this.data = data;
}
}
}
总得来说链表实现的栈跟链表本身的数据结构没多大的差别,原理都是一样的。只不过栈这种数据结构只能操作一个端。对链表熟悉了,对链表实现的栈也据不会陌生。文中的链表使用的是单向链表,并且以头节点作为栈顶,当然也可以使用尾节点作为链表,但是效率会降低。因为你每次操作第一个节点的效率总比你先走一遍遍历再找到最后一个节点的效率要高。如果是双向链表的话就头尾没什么区别。
利用栈先进后出的特性可以用来处理一些问题。例如字符串的倒序问题,就可以把每一个字符串压入栈,最后出栈。结果就是倒过来的了(这只是其中一种思路,当然又更加高效的犯法来实现)。