目录
栈的基本概念
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
即栈是后进先出的已种数据结构,即最后进入到栈中的数据是最先出来的。栈也根据存储方式的分为顺序存储和链式存储。
入栈
出栈
删除栈中的元素
若要删除栈中的1需要将1上的元素全部移出后才能进行相关操作。
删除后入栈
顺序栈 (由数组实现的顺序栈)
入栈:
- 判断栈是否满
- 若满则无法加入
- 未满则入栈,栈顶调整为该元素的索引
出栈:
- 判断是否为空
- 若为空则无法出栈
- 不为空则,将栈顶的元素移出
删除栈中的元素:
- 查找栈中是否有该元素
- 将该元素上面的元素由栈顶的元素开始,出栈移至另一个栈中,直至栈顶指向需要删除的元素
- 移出该元素
- 将暂存在另一个栈中的元素出栈,后加入原栈中。
public class Stack {
private int[] stack;
private int top; //存储栈顶
private int maxSize; //栈的最大长度
//栈的初始化,初始化最大的长度
public Stack(int maxSize){
this.maxSize=maxSize;
stack=new int[maxSize];
top=-1;
}
//栈的初始化,初始化最大的长度,默认为10
public Stack(){
this.maxSize=10;
stack=new int[maxSize];
top=-1;
}
//入栈
public int pop()throws Exception {
if (isEmpty()) {
throw new Exception("该栈为空");
}
return stack[top--];
}
//出栈
public void push(int param)throws Exception{
if(isFull()){
throw new Exception("该栈已满");
}
stack[++top]=param;
}
//删除栈中的元素
public void delete (int param)throws Exception{
int index=select(param);
int[] stack2=new int[top-index+1];
for(int i=0;i<stack2.length;i++){//将栈顶指向该元素的下一个元素,并将需删除的元素也加
stack2[i]=pop(); //入该中间栈
}
for(int i=stack2.length-2;i>=0;i--){//将需删除的元素外的元素重新加入栈中
push(stack2[i]);
}
}
//搜索栈中元素的索引
public int select(int param)throws Exception{
for(int i=top;i>=0;i--){
if(stack[i]==param){
return i;
}
}
throw new Exception("无该元素");
}
由栈顶遍历该栈
public void forEach(){
for (int i=top;i>=0;i--){
System.out.println(stack[i]);
}
}
//判断是否为空
public boolean isEmpty(){
if(top<0){
return true;
}
return false;
}
//判断是否满
public boolean isFull(){
if(maxSize<=top+1){
return true;
}
return false;
}
}
链栈(由链表实现)
链式栈是一种数据结构结构,可以通过单链表的方式来实现,使用链式栈的优点在于它能够克服用数组实现的顺序栈空间利用率不高的特点,但是需要为每个栈元素分配额外的指针空间用来存放指针域。
顺序栈是据于数组实现的,对数组的空间的使用效率并不是很高,若数组的内存用光了会有溢出问题,若未利用完该数组的空间也会造成空间的浪费。链式栈就能很好的解决在个问题。在入栈和出栈时动态的申请空间和释放空间。
入栈
- 加入该栈,并加入top的next后,并把top指向next中的地址
出栈
- 判断该栈是否为空
- 为空则抛出异常
- 不为空则将top指向top的上一个元素的地址
删除栈中元素
- 查找需要删除的元素
- 不存在则抛出异常,存在继续删除操作
- 将需删除的元素前的元素出栈,并保存在一个临时的链栈中
- 删除需删除的元素
- 将临时栈中的表加入栈中
public class LinkedStack { private int date; private LinkedStack top;//栈顶 private LinkedStack next; //下一个节点 public LinkedStack(){ } public LinkedStack(int date){ this.date=date; } //入栈 public void push(int date){ if(top==null){ this.date=date; top=this; }else { top.next=new LinkedStack(date); top=top.next; } } //出栈 public int pop()throws Exception{ if(top==null){ throw new Exception(); }else if(top==this){ top=null; return this.date; } LinkedStack before=selectTopBefore(); int date1=top.date; top=before; before.next=null; return date1; } //删除栈中的元素 public void delete(int date)throws Exception{ LinkedStack linkedStack=select(date); LinkedStack linkedStack1=new LinkedStack(); while (top!=linkedStack) { linkedStack1.push(this.pop()); } pop(); linkedStack1.forEach(); while (!linkedStack1.isEmpty()){ this.push(linkedStack1.pop()); } } //搜索该节点的地址 public LinkedStack select(int date)throws Exception{ LinkedStack linkedStack=this; while(linkedStack.date!=date){ linkedStack=linkedStack.next; if(linkedStack==null){ throw new Exception(); } } return linkedStack; } //搜索栈顶的前节点 public LinkedStack selectTopBefore(){ LinkedStack linkedStack=this; if(linkedStack==top){ return null; } while(linkedStack.next!=top){ linkedStack=linkedStack.next; } return linkedStack; } //遍历 public void forEach(){ LinkedStack linkedStack=this; while (linkedStack!=top){ System.out.println(linkedStack.date); linkedStack=linkedStack.next; } if(linkedStack!=null) { System.out.println(linkedStack.date); } } //判断是否为空 public boolean isEmpty(){ if(top==null){ return true; } return false; } }