在学数据结构课程时,对栈的最大特点是是后进先出(First In Last Out),对栈的操作主要是入栈和出栈,判断栈是否为空,计算栈的大小。
栈是一种数据结构,它代表只能在某一端进行插入、删除操作的特殊线性表。对栈而言,允许插入删除的一端是栈顶,另一端则称为栈底。
[color=red]1.栈的顺序存储实现:[/color]
运行结果:
[color=red]2.栈的链式存储实现:[/color]
java集合提供了两种栈供开发者使用:
java.util.Stack:一个普通的顺序栈,底层基于数组实现。这个Stack类是线程安全的。
java.util.LinkedList:是一个双向链表。线程不安全,可以当做栈来使用,提供了push(),pop(),peek()等方法。在多线程环境下使用,可以使用Collections类的工具方法将其改造成线程安全类。
栈是一种数据结构,它代表只能在某一端进行插入、删除操作的特殊线性表。对栈而言,允许插入删除的一端是栈顶,另一端则称为栈底。
[color=red]1.栈的顺序存储实现:[/color]
public class Stack
{
//存放栈内元素的数组
private Object[] elementData;
//记录栈内元素的个数
private int size = 0;
//以指定初始化容量创建一个Stack
private int capacityIncrement;
//以指定初始化容量创建一个Stack
public Stack(int initialCapacity)
{
elementData = new Object[initialCapacity];
}
public Stack(int initialCapacity , int capacityIncrement)
{
this(initialCapacity);
this.capacityIncrement = capacityIncrement;
}
//向“栈”顶压入一个元素
public void push(Object object)
{
ensureCapacity();
elementData[size++] = object;
}
public Object pop()
{
if(size == 0)
{
throw new RuntimeException("空栈异常");
}
return elementData[--size];
}
public int size()
{
return size;
}
//保证底层数组能容纳栈内所有元素
private void ensureCapacity()
{ //增加堆栈的容量
if(elementData.length==size)
{
Object[] oldElements = elementData;
int newLength = 0;
//已经设置capacityIncrement
if (capacityIncrement > 0)
{
newLength = elementData.length + capacityIncrement;
}
else
{
//将长度扩充到原来的1.5倍
newLength = (int)(elementData.length * 1.5);
}
elementData = new Object[newLength];
//将原数组的元素复制到新数组中
System.arraycopy(oldElements , 0 , elementData , 0 , size);
}
}
public static void main(String[] args)
{
Stack stack = new Stack(10);
//向栈顶压入10个元素
for (int i = 0 ; i < 10 ; i++)
{
stack.push("元素" + i);
System.out.println("元素" + i+"入栈");
}
//依次弹出10个元素
for (int i = 0 ; i < 10 ; i++)
{
System.out.println(stack.pop()+"出栈");
}
}
}
运行结果:
元素0入栈
元素1入栈
元素2入栈
元素3入栈
元素4入栈
元素5入栈
元素6入栈
元素7入栈
元素8入栈
元素9入栈
元素9出栈
元素8出栈
元素7出栈
元素6出栈
元素5出栈
元素4出栈
元素3出栈
元素2出栈
元素1出栈
元素0出栈
[color=red]2.栈的链式存储实现:[/color]
public class LinkStack<T>
{
//定义一个内部类Node,Node实例代表链栈的节点。
private class Node
{
//保存节点的数据
private T data;
//指向下个节点的引用
private Node next;
//无参数的构造器
public Node()
{
}
//初始化全部属性的构造器
public Node(T data , Node next)
{
this.data = data;
this.next = next;
}
}
//保存该链栈的栈顶元素
private Node top;
//保存该链栈中已包含的节点数
private int size;
//创建空链栈
public LinkStack()
{
//空链栈,top的值为null
top = null;
}
//以指定数据元素来创建链栈,该链栈只有一个元素
public LinkStack(T element)
{
top = new Node(element , null);
size++;
}
//返回链栈的长度
public int length()
{
return size;
}
//进栈
public void push(T element)
{
//让top指向新创建的元素,新元素的next引用指向原来的栈顶元素
top = new Node(element , top);
size++;
}
//出栈
public T pop()
{
Node oldTop = top;
//让top引用指向原栈顶元素的下一个元素
top = top.next;
//释放原栈顶元素的next引用
oldTop.next = null;
size--;
return oldTop.data;
}
//访问栈顶元素,但不删除栈顶元素
public T peek()
{
return top.data;
}
//判断链栈是否为空栈
public boolean empty()
{
return size == 0;
}
//清空链栈
public void clear()
{
//将底层数组所有元素赋为null
top = null;
size = 0;
}
public String toString()
{
//链栈为空链栈时
if (empty())
{
return "[]";
}
else
{
StringBuilder sb = new StringBuilder("[");
for (Node current = top ; current != null
; current = current.next )
{
sb.append(current.data.toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2 , len).append("]").toString();
}
}
}
java集合提供了两种栈供开发者使用:
java.util.Stack:一个普通的顺序栈,底层基于数组实现。这个Stack类是线程安全的。
java.util.LinkedList:是一个双向链表。线程不安全,可以当做栈来使用,提供了push(),pop(),peek()等方法。在多线程环境下使用,可以使用Collections类的工具方法将其改造成线程安全类。