0 课程地址
https://coding.imooc.com/lesson/207.html#mid=13418
1 重点关注
1.1 栈的基本实现 方式一之动态数组实现
参见代码3
1.2 栈的基本方法
入栈:push
出栈:pop
查看栈顶元素:peek(或top)
是否为空:isEmpty
栈的大小:getSize
2 课程内容
2.1 实际实现方式有多种
用户不关心底层如何实现的
3 Coding
3.1 核心代码
@Override public void push(E o) { arrayFan.addLast(o); } @Override public E pop() { return arrayFan.removLast(); } @Override public E peek() { return arrayFan.getLast(); } @Override public boolean isEmpty() { return arrayFan.isEmpty(); } @Override public int getSize() { return arrayFan.getSize(); }
3.2 全量代码
- 动态数组改造
package com.company; import java.util.Arrays; public class ArrayFan<E> { private int size; //int类型的数组 private E[] data; //1.1 创建构造函数,传入容量,则新生成一个数组 public ArrayFan(int capacity){ data = (E[]) new Object[capacity]; size = 0; } //1.2 创建无参构造函数 public ArrayFan(){ this(10); } //1.3 添加传入静态数组的构造函数 public ArrayFan(E[] param){ this.data = param; long outParm = Arrays.stream(param).filter(e->{ return e!=null; }).count(); this.size = (int)outParm; } //2.1 添加getSize,获取数组元素个数 public int getSize(){ return size; } //2.2 添加getCapacity,获取数组容量 public int getCapacity(){ return data.length; } //2.3 添加数组是否为空方法 public boolean isEmpty(){ return size==0; } //3.1 在数组末尾添加元素 public void addLast(E e){ addElement(size,e); } //3.2 在数组起始添加元素 public void addFirst(E e){ addElement(0,e); } //3.3 数组根据索引添加元素 public void addElement(int index,E e){ //1 校验异常 //1.1 如果数组已经满了,则禁止插入 if(size== data.length){ //todo 并不会,需要把值一条一条的赋进来 resize(2*size); //throw new IllegalArgumentException("数组已满,禁止插入"); } //1.2 如果传入的索引在已有数组的索引之外,则校验异常 if(index<0||index>size){ throw new IllegalArgumentException("索引应在已有数组的索引之间"); } //2 实现根据索引添加元素的逻辑 //2.1 data同步 for(int j = size-1;j>=index;j--){ data[j+1] = data[j]; } data[index] = e; //2.2 size同步 size++; } //6.1 数组动态伸缩 这里用size更好,想想为什么 private void resize(int capacity){ E[] newData = (E[]) new Object[capacity]; for(int i = 0;i < size;i++){ newData[i] = data[i]; } data = newData; } //4.1 数组 toString 范例 @Override public String toString() { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(String.format("Array:size = %d,capacity = %d\n",size,data.length)); stringBuffer.append("["); for(int i=0;i<size;i++){ stringBuffer.append(data[i]); if(i!=size-1){ stringBuffer.append(","); } } stringBuffer.append("]"); return stringBuffer.toString(); } //7.1 get第一个元素 public E getFirst(){ return get(0); } //7.2 get最后一个元素 public E getLast(){ return get(size-1); } //4.2 get获取元素 public E get(int index){ if(index<0||index>data.length){ throw new IllegalArgumentException("111"); } return data[index]; } //4.3 set获取元素 public void set(int index,E e){ if(index<0||index>data.length){ throw new IllegalArgumentException("111"); } data[index] = e; } //5.1 数组包含 public boolean contails(E e){ for(int i = 0;i<size;i++){ if(e.equals(data[i])){ return true; } } return false; } //5.2 数组搜索 public int search(E e){ for(int i = 0;i<size;i++){ if(e.equals(data[i])){ return i; } } return -1; } //5.3 数组删除,通常情况下做删除,会在出参把删除的值带出来 public E remove(int index){ if(index<0||index>=size){ throw new IllegalArgumentException("111"); } E outParm = data[index]; for(int i=index;i<size-1;i++){ data[i] = data[i+1]; } //这块不塞值也没有任何影响,因为size已经--了,不会访问到size之外的元素 data[size-1]= null; size--; if(size == data.length/2){ resize(data.length/2); } return outParm; } //5.4 删除首个元素 public E removFirst(){ return remove(0); } //5.5 删除最后的元素 public E removLast(){ return remove(size-1); } //5.6 删除指定的元素 public void removElement(E e){ int index = -1; //判断删除的元素是否存在 for(int i=0;i<size;i++){ if(e.equals(data[i])){ index = i; break; } } if(index>=0){ remove(index); }else{ throw new IllegalArgumentException("删除的元素未找到"); } } }
- 接口:
package com.company; /*** * * @author weidoudou * @date 2022/10/16 14:54 * @return null **/ public interface Stack<E> { /*** * 栈顶放入元素 * @author weidoudou * @date 2022/10/16 14:55 * @param e 请添加参数描述 * @return void **/ void push(E e); /** * 栈顶移出元素 * @author weidoudou * @date 2022/10/16 14:54 * @return void **/ E pop(); /** * 或者top 展示栈顶元素 * @author weidoudou * @date 2022/10/16 14:56 * @param * @return E **/ E peek(); /*** * 是否为空 * @author weidoudou * @date 2022/10/16 14:57 * @param * @return boolean **/ boolean isEmpty(); /** * 取得栈的大小 * @author weidoudou * @date 2022/10/16 14:57 * @param * @return int **/ int getSize(); }
- 实现类:
package com.company; /** * 用动态数组的方式实现栈 注意类和接口都有泛型 * @author weidoudou * @date 2022/10/16 14:58 * @return null **/ public class StackFirst<E> implements Stack<E>{ private ArrayFan<E> arrayFan; /** * 此处要添加初始化方法,否则没办法调用方法 * @author weidoudou * @date 2022/10/16 16:45 * @return null **/ public StackFirst(){ arrayFan = new ArrayFan<>(); } public StackFirst(int capacity){ arrayFan = new ArrayFan<>(capacity); } @Override public void push(E o) { arrayFan.addLast(o); } @Override public E pop() { return arrayFan.removLast(); } @Override public E peek() { return arrayFan.getLast(); } @Override public boolean isEmpty() { return arrayFan.isEmpty(); } @Override public int getSize() { return arrayFan.getSize(); } @Override public String toString() { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("Stack:"); stringBuffer.append("["); for(int i=0;i<arrayFan.getSize();i++){ stringBuffer.append(arrayFan.get(i)); if(i!=arrayFan.getSize()-1){ stringBuffer.append(","); } } stringBuffer.append("]"); stringBuffer.append("top"); //栈顶在此 return stringBuffer.toString(); } }
- 测试类:
package com.company; public class Main { public static void main(String[] args) { StackFirst<Integer> stackFirst = new StackFirst<>(); for(int i = 0;i < 5;i++){ stackFirst.push(i); System.out.println(stackFirst); } stackFirst.pop(); System.out.println(stackFirst); System.out.println(stackFirst.peek()); System.out.println(stackFirst.getSize()); System.out.println(stackFirst.isEmpty()); } }
- 测试结果:
---- IntelliJ IDEA coverage runner ---- sampling ... include patterns: exclude patterns: Stack:[0]top Stack:[0,1]top Stack:[0,1,2]top Stack:[0,1,2,3]top Stack:[0,1,2,3,4]top Stack:[0,1,2,3]top 3 4 false Class transformation time: 0.0181335s for 122 classes or 1.4863524590163934E-4s per class
诸葛