这个例子是课本上的一道习题,要求用单链表高效实现栈数据结构,并且不能使用头、尾节点。
1.先来谈谈比较艰难的一个思路
链表存储一个当前节点,当实现压入方法时,先判断当前节点是否存在,若为空则直接赋值,不为空,则添加到当前节点的next节点,并将当前节点转移到next节点。
链表同时存储根节点,当实现弹出方法时,采用遍历找到最后节点的pre节点,以删除最后节点,这样弹出方法需遍历,效率不高。
2.由于栈数据结构的特性,最主要要关注弹出、压入端的高效实现,接下来考虑如下算法
链表存储一个当前节点,当实现压入方法时,将压入节点的next链与当前节点相连,并将当前节点转移到压入节点。
当实现弹出方法时,获取当前节点的next节点作为当前节点,并将之前的当前节点弹出,此方法不需遍历,只消耗常数时间。
3.代码实现如下
/**
* 单链表实现栈数据结构
* @author swing
*
*/
public class SLStack {
private Node curr;//当前节点
private int size;//栈大小
/**
* 压入
* @param data 压入节点值
* @return 压入节点值
*/
public int push(int data)
{
//1.先包装节点
Node node = new Node(data);
//2.如果当前节点为空,直接赋值。否则赋值给当前节点的next链并转移当前节点
if(curr == null)
{
curr = node;
}
else
{
node.setNext(curr);
curr = node;
}
//3.增加栈大小
size++;
return data;
}
/**
* 弹出
* @return 弹出节点值
*/
public int pop()
{
//1.栈大小至少为1时可进行弹出操作
if(size > 0)
{
//2.将当前节点缓存
Node temp = curr;
//3.获取当前节点的next链作为新的当前节点
curr = curr.getNext();
//3.栈大小减少
size--;
return temp.getData();
}
else
{
throw new IndexOutOfBoundsException("空栈");
}
}
/**
* 栈大小
* @return 栈大小
*/
public int size()
{
return size;
}
}