数据结构——栈
相关概念介绍
栈是一种线性结构,里面的数据元素遵循“先进后出”的原则,可以把栈想成一个容器(看下图)——上开口下封闭的容器,要对数据元素进行操作只能在栈顶进行
栈的抽象类描述
栈是有限序列,数据元素类型可以任意,但只要是同一种类型即可。栈的基本操作有:
clear():置空操作,将一个栈置成空栈
isEmpty():判断一个栈是否为空,是就返回true,否则返回false
length():返回栈中元素个数
peek():取栈顶元素返回其值,若为空栈则返回null
push(x):将数据元素x压入栈顶(入栈)
pop():删除并返回栈顶元素(出栈)
栈的实现
栈的实现有两种:顺序栈和链栈
1. 顺序栈
顺序栈使用数组来实现,和顺序表一样。我们加一个变量top来指明栈顶元素的位置,top有两种表示方法:top=0 或 top=-1。
top=0表示指向栈顶元素存储位置的下一个存储单元位置
top=-1表示指向栈顶元素的存储位置
顺序栈类
这里采用char数组为例子实现顺序栈类的描述
public class Istack {
public char[] arr;//用数组表示栈元素
public int maxsize;//栈容量大小
public int top;//top指针
public Istack(int msize) { //初始化栈
this.arr = new char[msize];
this.maxsize = msize;
this.top = -1;
}
public void clear() {//置空栈
top = 0;
}
public boolean isEmpty() {//判断是否为空栈
if(top==-1) {
return true;
}
else {
return false;
}
}
public int length() {//返回栈的长度
return top+1;
}
public char peek() {//取栈顶元素
if(top==-1) {
return 0;
}
else {
return arr[top];
}
}
public void push(char x) {//入栈
if(top == maxsize-1) {
System.out.println("栈已满,"+x+"无法入栈");
}
else {
System.out.println(x+"入栈");
arr[++top] = x;
}
}
public char pop() {//出栈
if(top == -1) {
System.out.println("栈为空");
return 0;
}
else {
char temp = arr[top];
top--;
System.out.println(temp+"出栈");
return temp;
}
}
}
2.链栈
链栈使用链表进行存储,不过相当于给链表加了约束——“先进后出”,使得对于链栈的操作只能在链表的尾部最后一个元素进行操作,因而我们可以知道尾部最后一个结点即为栈顶,头部第一个结点即为栈底
链栈的结点类描述
public class stack_Node<T> {
T data;
public stack_Node<T> next;
public stack_Node() {
this.data = null;
this.next = null;
}
public stack_Node(T data) {
this.data = data;
this.next = null;
}
public stack_Node(T data,stack_Node<T> next) {
this.data = data;
this.next = next;
}
}
链栈的实现类描述
public class liststack<T> {
public stack_Node<T> head;
stack_Node<T> top;
public liststack() {//初始化头结点
head = new stack_Node<T>();
top = head;
}
public void clear() {
top = null;
}
public boolean isEmpty() {
if(head.next!=null) {
return true;
}
else {
return false;
}
}
public int length() {//返回栈的长度
int l = 0;//记录长度
stack_Node<T> p = head;
if(p.next!=null) {
p = p.next;
l++;
}
return l;
}
public T peek() {//取栈顶元素
if(head.next == null) {
return null;
}
else {
return top.data;
}
}
public void push(T data) {//入栈
stack_Node<T> newnode = new stack_Node<T>(data);
newnode.next = top;
head.next = newnode;
top = newnode;
}
public T pop() {//出栈
if(head.next == null) {
System.out.println("这是空栈");
return null;
}
else {
stack_Node<T> p = new stack_Node<T>();
p = top;
head.next = head.next.next;
top = head.next;
return p.data;
}
}
}
总结
一般来说,我们在选择栈的存储结构时,优先考虑链栈,因为它不像数组那样有固定的长度,它可以更加自由地进行相关的操作