栈
- 关于栈就是建立在数组或者链表的一种逻辑结构,在接下来的内容中,我将通过顺序存储结构来为大家讲解栈和队列.
- 首先栈的特点是先进后出.它所包含的方法分别由入栈 push(),出栈 pop(),查找栈中最后的一个元素 peek()与判断栈是否为空栈 isEmpty().首先我们需要创建一个栈,为了与编译器中自带的栈区分开,我选择为自己的栈重新定义一个接口为Stack_I,然后在这个接口中定义栈的方法,之后再创建一个类来实现这个接口,由此来获得我们自己的栈.
- 创建栈的第一步就是在类中定义一个储存数据的容器,和容器中有多少个元素.而关于储存数据的容器类型我已经为大家定义好了一个完整的,如果大家有其他的需要可以去修改这个类
-
public class MyArray<T> { private T[] data;//保存数据 int size;//数组中实际存放元素的个数 int capacity;//容积 public MyArray(int capacity){ if(capacity<=0){ this.capacity=10; }else { this.capacity = capacity; } this.size=0; this.data=(T[])(new Object[this.capacity]); } //获取数组中实际存放元素的个数 public int getSize(){ return this.size; } //获取数组的容积 public int getCapacity(){ return this.capacity; } //判断数组是否为空 public boolean isEmpty(){ return this.size==0; } // 向数组中添加元素 public void add(T item){ //this.size 指向的是待插入元素的位置 addIndex(this.size,item); } // 向数组中指定位置添加元素 public void addIndex(int index,T val){ if(index<0||index>this.size){ throw new IllegalArgumentException("index is invaild!"); } if(this.capacity==this.size){ resize(capacity*2); } //从index位置开始元素需要向后移动 for (int i = this.size-1; i >=index ; i--) { this.data[i+1]=this.data[i]; } this.data[index]=val; this.size++; } private void resize(int newCapacity){ T[] newData=(T[])new Object[newCapacity]; for (int i = 0; i < this.size; i++) { newData[i]=data[i]; } this.data=newData; this.capacity=newCapacity; } // 向数组头部添加元素 public void addHead(T val){ addIndex(0,val); } //修改指向位置的值 public void modifyValueByIndex(int index,T item){ //入参一定判断 if (index <0||index>=this.capacity) { throw new IllegalArgumentException("index is invaild!"); } this.data[index]=item; } //获取指定索引位置的值 public T getValueByIndex(int index){ if (index <0||index>=this.capacity) { throw new IllegalArgumentException("index is invaild!"); } return this.data[index]; } //获取数组中最后一个位置的元素的值 public T getValueFromLast(){ return getValueByIndex(this.size-1); } //查找指定的值在数组中是否存在,存在获取索引,不存在返回-1 public int containValue(T val){ for (int i = 0; i < this.size; i++) { if(val.equals(this.data[i])){ return i; } } return -1; } //根据索引在数组中删除元素 public T removeByIndex(int index){ if (index <0||index>=this.capacity) { throw new IllegalArgumentException("index is invaild!"); } //删除元素的核心 T delValue = this.data[index]; for (int i = index+1; i <this.size ; i++) { this.data[i-1]=this.data[i]; } this.size--; if(this.size<=this.capacity/4&&this.capacity/2>0){ resize(this.capacity/2); } return delValue; } //删除数组尾部的元素 public T removeFromLast(){ return removeByIndex(this.size-1); } @Override public String toString() { StringBuilder sb=new StringBuilder("{"); for (int i = 0; i < this.size; i++) { sb.append(this.data[i]); if(i!=this.size-1){ sb.append(","); } } sb.append("}"); return sb.toString(); }
将这个容器类型定义好之后,我们继续构造我们的栈
-
public class ArrStack<T> implements Stack_I<T> { private MyArray<T> data; //栈的容器 int size; public ArrStack(){ this.data=new MyArray<>(100); this.size=0; } }
由于我们不确定容器内元素是什么数据类型的,所以用泛型来代替.之后我们来分别实现该类接口中的方法
- 首先是入栈的方法
public void push(T ele) { this.data.add(ele); this.size++; }
接着是出栈的方法
-
public T pop() { if(isEmpty()){ return null; } return this.data.removeFromLast(); }
再然后就是查找栈中最后一个元素的方法
-
public T peek() { if(isEmpty()){ return null; } return this.data.getValueFromLast(); }
最后是判断栈是否为空的方法
-
public boolean isEmpty() { return this.data.getSize()==0; }
最后我们将其卸载一个类中,就构建出了一个属于我们自己的最基本的栈(后面附有该栈接口类)
-
public class ArrStack<T> implements Stack_I<T> { private MyArray<T> data; //栈的容器 int size; public ArrStack(){ this.data=new MyArray<>(100); this.size=0; } @Override public void push(T ele) { this.data.add(ele); this.size++; } @Override public T pop() { if(isEmpty()){ return null; } return this.data.removeFromLast(); } @Override public T peek() { if(isEmpty()){ return null; } return this.data.getValueFromLast(); } @Override public boolean isEmpty() { return this.data.getSize()==0; } }
public interface Stack_I<T> {
//入栈
void push(T ele);
//出栈
T pop();
//查栈
T peek();
//判断栈是否为空
boolean isEmpty();
}