栈定义
栈(stack):是一种特殊的串行形式的数据结构,其特殊之处在于只允许在链接串行或者阵列的
一端进行插入、删除操作。其实现方式可以通过一维阵列和链接串行来实现。
Tips:简单的来说栈其实也是一种操作受限的线性表。是一种后进先出的数据结构可以使用数
组或者链表的形式来实现。
栈的操作表现形式:
栈实现
知道了栈的定义,我们来看看栈的实现吧。首先我们需要明白的的是栈具有哪些操作。
通过一个接口定义其操作。
package com.kiritor; /** * 栈操作定义 * @author Kiritor*/ public interface Stack<T> { /*判空*/ boolean isEmpty(); /*清空栈*/ void clear(); /*弹栈*/ T pop(); /*入栈*/ boolean push(T data); /*栈的长度*/ int length(); /*查看栈顶的元素,但不移除它*/ T peek(); /*返回对象在栈中的位置*/ int search(T t); }
栈的数组实现
栈的数组实现,底层使用数组
package com.kiritor; /** * 栈的数组实现 * @author Kiritor*/ public class ArrayStack<T> implements Stack<T>{ private T[] t = (T[]) new Object[16];//栈空间默认为16 private int size = 0; @Override public boolean isEmpty() { return size==0; } @Override public void clear() { for(int i = 0;i<t.length;i++) t[i]=null;//将其引用只为null,方便gc进行回收 size = 0;//栈的大小置0 } /*弹栈操作*/ @Override public T pop() { if(size==0) return null; else { T tmp = t[size-1]; t[size-1]=null;//便于gc回收 size--; return tmp; } } @Override public boolean push(T data) { if(size>=t.length) { //栈空间已满,需要扩容 resize(); } t[size++]=data; return true; } public void resize() { T[] tmp = (T[]) new Object[t.length*2]; for(int i = 0;i<t.length;i++){ tmp[i]=t[i]; t[i]=null;//便于gc处理 } t = tmp; tmp = null;//便于gc处理,提高程序效率 } @Override public int length() { return size; } /*查看栈顶元素,但是并不删除*/ @Override public T peek() { if(size==0) return null; else { return t[size-1]; } } /*下表从1开始*/ @Override public int search(T t) { for(int i= 0;i<size;i++) if(t.equals(this.t[i])) return i+1; return 0; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ArrayStack:\n[\n"); for (int i = size-1; i >=0; i--) { sb.append(" "+t[i].toString()); if (i != size + 1) { sb.append("\n"); } } sb.append("]"); return sb.toString(); } }
测试代码:
public static void main(String[] args) { ArrayStack<String> arrayStack = new ArrayStack<>(); arrayStack.push("C语言"); arrayStack.push("C++"); arrayStack.push("JAVA"); arrayStack.push("数据结构"); arrayStack.pop(); arrayStack.peek(); arrayStack.pop(); System.out.println(arrayStack.toString()); }
输出结果:
栈的链表实现
package com.kiritor; /** * 栈的链表实现 * @author Kiritor*/ public class LinkStack<T> implements Stack<T>{ /*将数据封装成结点*/ class Node { private Node pre; private T data; } /*栈顶指针*/ private Node top; private int size;//栈的大小 public LinkStack() { this.top = null; this.size = 0; } @Override public boolean isEmpty() { return size==0; } @Override public void clear() { top = null; size = 0; } @Override public T pop() { if (top != null) { T t = top.data; // 改变栈顶指针 top = top.pre; size--; return t; } return null; } @Override public boolean push(T data) { Node node = new Node(); node.data = data; node.pre = top; // 改变栈顶指针 top = node; size++; return true; } @Override public int length() { return size; } @Override public T peek() { return top.data; } /*下表从1开始*/ @Override public int search(T t) { int count=0; for(Node node= top;node.pre!=null;node = node.pre) { count++; if(t.equals(node.data)) return size - count; } return 0; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("LinkStack:"+length()+"\n[\n"); int count=0; for (Node node = top;node!=null;node=node.pre) { count++; sb.append(" "+node.data.toString()); if (count != size + 1) { sb.append("\n"); } } sb.append("]"); System.out.println(count); return sb.toString(); } }
测试代码:
public static void main(String[] args) { LinkStack<String> arrayStack = new LinkStack<>(); arrayStack.push("C语言"); arrayStack.push("C++"); arrayStack.push("JAVA"); arrayStack.push("数据结构"); System.out.println(arrayStack.toString()); }
结果就不贴出了
因为栈操作的特殊性,一般来说以数组方式实现的栈的效率是要高于链表实现的,
原因在于:其一数组的访问更快。其二由于只在栈顶进行操作并未涉及太大的元素移动
但是使用链式实现将数据包装成Node,在从其中取数据,还的维护栈顶指针和前驱指针。
转载于:https://blog.51cto.com/kiritor/1226683