栈
什么是栈
栈是一种用于存储数据的简单数据结构(与链表类似)。数据入栈的次序是栈的关键。
栈(stack)是一个有序线性表,只能在表的一端(称为栈顶,top)执行插入和删除操作。最后插入的元素总是被第一个删除。所以,栈也称为后进先出(Last In First Out,FIFO)或者先进后出(First In Last Out,FILO)
栈的抽象数据类型
主要操作
- void push(int data) :将数据插入栈
- int pop():删除并返回最后一个插入栈的元素
栈的辅助操作
- int top():返回最后一个插入栈的元素,但不删除
- int size():返回存储在栈中的元素的个数
- int isEmpty():判断栈中是否有元素
- int isStackFull():判断栈中是否满元素
实现
通过简单数组实现
/*数组实现栈
* */
public class ArrayStack {
private long[] a;
private int size;//栈数组的大小
private int top;//栈顶
public ArrayStack(int maxSize) {
this.size = maxSize;
this.a = new long[size];
this.top = -1;//表示空栈
}
//入栈
public void push(long value){
if(isFull()){
System.out.println("栈已经满!");
return;
}
a[++top] = value;
}
//返回栈顶内容,但是不删除
public void peek(){
if(isEmpty()){
System.out.println("栈中没有数据!");
}
System.out.println(a[top]);
}
//弹出栈顶内容,删除
public long pop(){
if(isEmpty()){
System.out.println("栈中没有数据!");
return 0;
}
return a[top--];
}
public int size(){
return top + 1;
}
public boolean isEmpty() {
return (top == -1);
}
public boolean isFull() {
return (top == size - 1);
}
//显示
public void display(){
for (long l : a) {
System.out.println("["+l+"]");
}
}
}
@Test
public void testArrayStack(){
ArrayStack arrayStack = new ArrayStack(3);
arrayStack.display();
System.out.println(">>>>1");
System.out.println(arrayStack.isEmpty());
System.out.println(arrayStack.isFull());
System.out.println(">>>>>beforePush");
arrayStack.push(4);
arrayStack.push(2);
arrayStack.push(7);
arrayStack.display();
System.out.println(">>>>>afterPush");
arrayStack.peek();
arrayStack.pop();
arrayStack.display();
System.out.println(arrayStack.isEmpty());
System.out.println(arrayStack.isFull());
输出结果:
[0]
[0]
[0]
>>>>1
true
false
>>>>>beforePush
[4]
[2]
[7]
>>>>>afterPush
7
[4]
[2]
[7]
false
false
Process finished with exit code 0
}
动态数组实现
其实具体实现代码和上面一样,加多一条动态扩展数组功能
public void doubleArray(){
long newArray[] = new long[size*2];
System.arraycopy(a,0,newArray,0,size);
size = size * 2;
a = newArray;
}
只需在栈满时候,调用上面的方法即可。
链表实现
/*链表*/
public class LLNode {
private int data;//存放数据
private LLNode next;//指向下一个节点
public LLNode() {
}
public LLNode(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public LLNode getNext() {
return next;
}
public void setNext(LLNode next) {
this.next = next;
}
}
/*链表实现的栈*/
public class LLStack{
LLNode headnode = null;
public LLStack() {
headnode = new LLNode();//初始化栈
}
public boolean isEmpty(){
return headnode ==null;
}
public void push(int data) {
if (isEmpty()){
headnode = new LLNode(data);
}else {
LLNode llNode = new LLNode(data);
llNode.setNext(headnode);
headnode = llNode;
}
}
public int pop(){
if(isEmpty()){
System.out.println("栈为空");
return 0;
}
int data = headnode.getData();
headnode = headnode.getNext();
return data;
}
public int top(){
if(isEmpty()){
System.out.println("栈为空");
return 0;
}
int data = headnode.getData();
return data;
}
public int length(){
int count = 0;
LLNode temp = headnode;
if(isEmpty()){
return count;
}else {
while (temp!=null){
count++;
temp = temp.getNext();
}
count++;
return count;
}
}
}
栈的三种实现方法的比较
基于数组实现的
- 各个操作都是常数时间的开销
- 每隔一段时间倍增操作的开销较大
- (从空栈开始)n个操作的任意序列的平摊时间开销为O(n)
基于链表实现的
- 栈规模的增加减小都很简洁
- 各个操作都是常数时间的开销
- 每个操作都是要使用额外的空间和时间来处理指针
本人学习的理解笔记,如有错误!不吝赐教,请留言,谢谢你!