基础数据结构-栈
基本概念
栈:后入先出(LIFO),特殊的线性表
栈如何实现 其实它是一个仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对的另一端是栈底。向一个栈插入新元素又称为进栈、入栈、压栈。它是把新元素放到栈顶元素上边使其成为新的栈顶元素:从一个栈删除元素又称作出栈活退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。 栈其实是一个特殊的链表或者数组 既然栈也是一个线性表,那么我们肯定会想到数组和链表,而且栈还有很多限制,为什么还要使用栈,而不直接用数组和链表。 数组和链表暴露太多的接口,实现上更灵活,有些技术理解不到位的人员可能出错。所以在某些特定场合下最好选用栈这个数据结构。
栈的分类:
1.基于数组的栈——以数组为底层数据结构时,通常以数组头为栈底,通常以数组头到数组尾为栈顶的生长方向。 2.基于单链表的栈——以链表为底层的数据结构时:以链表头为栈顶,便于插入和删除,压栈产生的新节点将一直出现在链表的头部。
两种类型的最大区别就是扩容,链表天然支持动态扩容,使用栈多使用数组,防止栈溢出
栈的基本操作:
1.入栈(push) 2.出栈(pop)
代码实现
package Stack;
public interface Mystack<Item> {
Mystack<Item> push(Item item);
Item pop ();
int size();
boolean isEmpty();
}
package Stack;
public class ArrayStack<Item> implements Mystack<Item>{
private Item []a=(Item[]) new Object[1];
private int n=0;
public ArrayStack(int cap){
a=(Item[]) new Object [cap];
}
public Mystack<Item> push(Item item) {
JudgeSize();
a[n++]=item;
return null;
}
private void JudgeSize(){
if (n>=a.length){
resize(2*a.length);
}else if (n>0 && n<a.length/2){
resize(a.length/2);
}
}
private void resize(int size){
Item []temp = (Item[]) new Object[size];
for (int i=0;i<n;i++){
temp [i]=a[i];
}
a=temp;
}
public Item pop() {
if(isEmpty()){
return null;
}
Item item = a[--n];
a[n]=null;
return item;
}
public int size() {
return n;
}
public boolean isEmpty() {
return 0==n;
}
}
例题
数学表达式求值 用栈实现一个简单的四则运算:3+11*2+8-15/5 思路:用两个栈来实现:一个放数字,一个放符号 我们从头开始遍历这个算术表达式: 1.遇到的是数字我们直接入栈到数字栈里 2.遇到的是符号就把符号栈的栈顶拿出来做比较,如果说他比栈顶符号的优先级高就直接入栈,如果比符号栈栈顶的符号优先级低或者相同,就从符号栈中取栈顶符号进行计算(从数字栈中取栈顶的2个数),计算完的结果还要再放入数字栈中
面试经典: 1.如何设计一个括号匹配功能?比如给你一串括号让你判断是否符合我们的括号原则,如下所示: [(){()}{}] 符合 [][]{(}) 不符合
package Stack;
import java.util.Scanner;
public class BracketsStack {
public static boolean isOK(String s){
Mystack<Character> brackets = new ArrayStack<Character>(20);
char c[]=s.toCharArray();
Character top;
for (char x:c){
switch (x) {
case '{':
case '(':
case '[':
brackets.push(x);
break;
case'}':
top = brackets.pop();
if(top==null)return false;
if (top=='{'){
break;
}else{
return false;
}
case']':
top = brackets.pop();
if(top==null)return false;
if (top=='['){
break;
}else{
return false;
}
case')':
top = brackets.pop();
if(top==null)return false;
if (top=='('){
break;
}else{
return false;
}
default:
break;
}
}
return brackets.isEmpty();
}
public static void main(String[] args) {
Scanner scanner =new Scanner(System.in);
while (scanner.hasNext()){
String s= scanner.next();
System.out.println("s匹配的结果是:"+isOK(s));
}
}
}
2.如何设计一个浏览器的前进和后退功能? 用两个栈,一个前进栈一个后退栈 点击前进把后退栈出栈进入到前进栈,反之点后退就前进栈出栈进入到后退栈。点击新页面将后退栈清空 如图
|