1.栈的概念
1.栈的定义
栈是仅限在表尾进行插入和删除的线性表,栈又被称为先进后出的线性表,简称“LIFO”
我们这次用数组作为我们栈的底层数据结构,代码会放到结尾供大家参考使用
2.栈顶的定义
栈是一个线性表,我们允许插入和删除的一端称为栈顶
3.栈底的定义
和栈顶相对的另一端称为栈底,实际上栈底的元素我们不需要关心
4.栈的创建
//数据容器
private T[] data;
//容积
private int capacity;
//实际存放的元素个数
private int size;
2.入栈
1.入栈的定义
栈元素的插入操作叫做入栈,也可以称为进栈、压栈
2.动画演示
图中是以链表为底层数据结构的,大家看图了解个大概就可以了,具体可以看代码是怎么实现的
3.代码实现
//在末尾添加元素
public void addTail(T val) {
//this.data[size]=val;
this.add(this.size, val);
}
//在中间插入元素
public void add(int index, T val) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
//判断数组是否满
if(this.size==this.capacity){
//数组满的话扩容原来数组的两倍
int newCapacity=this.capacity*2;
T[] newDate=(T[]) new Object[newCapacity];//创建一个新的数组
//进行数组迁移
for (int i = 0; i < this.size; i++) {
newDate[i]=this.data[i];
}
this.capacity=newCapacity;
this.data=newDate;
}
3.出栈
1.出栈的定义
栈元素的删除操作叫做出栈,也可称为弹栈
2.动画演示
3.代码演示
//移出末尾
public T removeTail() {
// T val=this.data[size-1];
// this.size-=1;
// return val;
return this.remove(this.size);
}
//中部移出
public T remove(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
T val = this.data[index];
for (int i = index; i < this.size; i++) {
this.data[i] = this.data[i+1];
}
this.size -= 1;
if(this.size<=this.capacity/4&&this.capacity/2>1){
int newCapacity=this.capacity/2;
T[] newDate=(T[])new Object[newCapacity];
for (int i = 0; i < this.size; i++) {
newDate[i]=this.data[i];
}
this.capacity=newCapacity;
this.data=newDate;
}
4.查询栈顶
1.获取栈顶的定义
一般我们可以去查看栈顶的元素是什么
2.动画演示
3.代码演示
public T peek(T val) {
return data.getEnByIndex(this.size() - 1);
}
//获得指定索引的元素
public T getEnByIndex(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
return this.data[index];
}
基本的栈能用到的就这些基本的方法,接下来给大家一个完整的代码,供大家学习参考
public class StackDemo<T> implements Stack<T> {
//以我们封装的数组作为栈的底层数据结构
private arrSub<T>data;
public StackDemo() {
data=new arrSub<>();
}
public StackDemo(int capacity) {
data=new arrSub<>(capacity);
}
@Override//弹栈
public T pop() {
return data.removeTail();
}
@Override//往栈中添加元素
public void push(T val) {
data.addTail(val);
}
@Override//查看元素个数
public int size() {
return data.getSize();//获得数组元素个数
}
@Override//判断是否为空
public boolean isEmpty() {
return data.isEmpty();
}
@Override//查看栈顶元素
public T peek(T val) {
return data.getEnByIndex(this.size() - 1);
}
@Override
public T peek() {
return null;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("栈顶[");
T[] arr = data.getData();
for (int i = size() - 1; i >= 0; i--) {
sb.append(arr[i]);
if (i != 0) {
sb.append(",");
}
}
sb.append("]栈底");
return sb.toString();
}
public static void main(String[] args) {
Stack<String> stack = new StackDemo<>(10);
String[] fruits
= {"apple", "banana", "peach", "watermelon", "strawberry", "pear", "orange", "grape"};
for (int i = 0; i < fruits.length; i++) {
stack.push(fruits[i]);
}
System.out.println(stack);
while (!stack.isEmpty()) {
System.out.println("ele-->" + stack.pop());
System.out.println(stack + "栈中元素的个数:" + stack.size());
}
}
}
public class arrSub<T> {
//数据容器
private T[] data;
//容积
private int capacity;
//实际存放的元素个数
private int size;
public arrSub(int capacity) {
this.capacity = capacity;
this.data = (T[]) new Object[this.capacity];
this.size = 0;
}
public arrSub() {
this.capacity = 10;
}
// 判断数据容器是否为空
public boolean isEmpty() {
return this.size == 0;
}
public T[] getData(){
return this.data;
}
//获得数组的容积
public int getCapacity() {
return this.capacity;
}
//获取元素的个数
public int getSize() {
return this.size;
}
//首行添加元素
public void addTop(T val) {
// for (int i = size-1; i >=0 ; i--) {
// this.data[i+1]=this.data[i];
// }
// this.data[0]=val;
this.add(0, val);
}
//在末尾添加元素
public void addTail(T val) {
//this.data[size]=val;
this.add(this.size, val);
}
//在中间插入元素
public void add(int index, T val) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
//判断数组是否满
if(this.size==this.capacity){
//数组满的话扩容原来数组的两倍
int newCapacity=this.capacity*2;
T[] newDate=(T[]) new Object[newCapacity];//创建一个新的数组
//进行数组迁移
for (int i = 0; i < this.size; i++) {
newDate[i]=this.data[i];
}
this.capacity=newCapacity;
this.data=newDate;
}
for (int i = this.size - 1; i >= index; i--) {
this.data[i + 1] = this.data[i];
}
this.data[index] = val;
this.size += 1;
}
//获得指定索引的元素
public T getEnByIndex(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
return this.data[index];
}
//获得指定元素的索引
public int getEnByVal(int index, T val) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
for (int i = 0; i < this.size; i++) {
if (this.data[i] == val) {
return i;
}
}
return -1;
}
//判断是否包含某种布局
public boolean contains(T val) {
for (int i = 0; i < this.size; i++) {
if (this.data[i] == val) {
return true;
}
}
return false;
}
//修改指定索引的元素
public void upLoad(T var, int index) {
if (index < 0 || index > this.size) {
throw new IllegalArgumentException("index is invalid!");
}
this.data[index] = var;
}
//重写toString的方法
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder(10);
for (int i = 0; i < this.size; i++) {
stringBuilder.append(this.data[i] + ",");
}
return stringBuilder.substring(0, stringBuilder.lastIndexOf(",") == -1 ? 0 : stringBuilder.lastIndexOf(","));
}
//移出末尾
public T removeTail() {
// T val=this.data[size-1];
// this.size-=1;
// return val;
return this.remove(this.size);
}
//移出首部
public T removeTop() {
// T val=this.data[0];
// for (int i = 1; i <this.size; i++) {
// this.data[i-1]=this.data[i];
// }
// this.size-=1;
// return val;
return this.remove(0);
}
//中部移出
public T remove(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is invalid!");
}
T val = this.data[index];
for (int i = index; i < this.size; i++) {
this.data[i] = this.data[i+1];
}
this.size -= 1;
if(this.size<=this.capacity/4&&this.capacity/2>1){
int newCapacity=this.capacity/2;
T[] newDate=(T[])new Object[newCapacity];
for (int i = 0; i < this.size; i++) {
newDate[i]=this.data[i];
}
this.capacity=newCapacity;
this.data=newDate;
}
return val;
}
public static void main(String[] args) {
arrSub myArr = new arrSub(50);
for (int i = 1; i <= 20; i++) {
myArr.addTail(i + 10);
}
System.out.println(myArr);
// System.out.println("20?" + myArr.contains(20));
// System.out.println("50?" + myArr.contains(50));
while (!myArr.isEmpty()) {
myArr.removeTail();
System.out.println(myArr);
}
}
leetcode题单:
从尾到头打印链表
public int[] reversePrint(ListNode head) {
LinkedList<Integer> stack = new LinkedList<Integer>();
while(head != null) {
stack.addLast(head.val);
head = head.next;
}
int[] res = new int[stack.size()];
for(int i = 0; i < res.length; i++)
res[i] = stack.removeLast();
return res;
}
括号的最大嵌套深度
public int maxDepth(String s) {
int ans = 0, size = 0;
for (int i = 0; i < s.length(); ++i) {
char ch = s.charAt(i);
if (ch == '(') {
++size;
ans = Math.max(ans, size);
} else if (ch == ')') {
--size;
}
}
return ans;
}
回文链表
public boolean isPalindrome(ListNode head) {
if(head==null){
return false;
}
StringBuilder s1=new StringBuilder();
StringBuilder s2=new StringBuilder();
while(head!=null){
s1.append(head.val);
s2.append(head.val);
head=head.next;
}
s2.reverse();
return s1.toString().equals(s2.toString());}
这里以数组为底层结构的队列代码供大家参考
import java.util.Optional;
public class ArrQueue<T> implements Queue<T> {
// 队列的容器
CycleArray<T> data;
// 构造函数
public ArrQueue() {
data = new CycleArray<>();
}
public ArrQueue(int capacity) {
this.data = new CycleArray<>(capacity);
}
@Override
public void offer(T ele) {
data.addTail(ele);
}
@Override
public T poll() {
return data.removeHead();
}
@Override
public int size() {
return data.getSize();
}
@Override
public boolean isEmpty() {
return data.isEmpty();
}
@Override
public T peek() {
Optional<T> optional = data.getFront();
if (optional.isPresent()) {
return optional.get();
}
return null;
}
@Override
public String toString() {
return data.toString();
}
}
import java.util.Optional;
/*解决了队列删除时的时间复杂度O(n),循环队列删除时的时间复杂度为O(1)
* 假设有两个索引,front-->始终指该数组的第一个元素 tail-->始终指向元素插入位置
* 如果front==tail时,该循环数组为空
* 如果(tail+1)%capacity=front时,该数组为满状态
*
* */
/**
* 循环队列的底层容器
*/
public class CycleArray<T> {
// 数据容器
private T[] data;
// 容积
private int capacity;
// 实际存放元素的个数
private int size;
// 声明两个索引 front--队首 tail--队尾
int front = 0;
int tail = 0;
// front === tail 队列是空的 (tail+1)/capacity == front 队列是满的
public CycleArray() {
this(10);
}
public CycleArray(int capacity) {
this.capacity = capacity + 1;//因为要浪费一个空间,所以在这里要多加一个空间
this.data = (T[]) new Object[this.capacity];// 浪费一个空间
this.size = 0;
}
public T[] getData() {
return this.data;
}
// 1、队列是否为空
public boolean isEmpty() {
return this.front == this.tail;
}
// 2、获取数组的容积
public int getCapacity() {
return this.capacity;
}
//3、获取实际存放元素的个数
public int getSize() {
return this.size;
}
// 在队列的尾部添加元素(tail指向待插入元素的位置)
public void addTail(T val) {
// 当队列已满,要进行扩容
if ((this.tail + 1) % this.capacity == this.front) {
// 新的容积
int newCapacity = 2 * (this.capacity - 1);
resize(newCapacity);
}
// 将val插入到队列的尾部
this.data[this.tail] = val;
// tail向后移动
this.tail = (this.tail + 1) % capacity;
// 更新size的值
this.size += 1;
}
private void resize(int newCapacity) {
T[] newData = (T[]) new Object[newCapacity + 1];
// 迁移数据 this.front
int cur = this.front;
int index = 0;
while (cur != this.tail) {
newData[index++] = this.data[cur];
cur = (cur + 1) % this.capacity;
}
// 修改属性
this.capacity = newCapacity + 1;
this.data = newData;
this.front = 0;
this.tail = this.size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
int cur = this.front;
while (cur != this.tail) {
sb.append(this.data[cur]);
if ((cur + 1) % this.capacity != this.tail) {
sb.append(",");
}
cur = (cur + 1) % this.capacity;
}
sb.append("[" + this.front + "<-->" + this.tail + "]");
return sb.toString();
}
//从队列中移除元素
public T removeHead() {
// 1、队列是否为空
if (this.front == this.tail) {
return null;
}
T val = this.data[this.front];
this.front = (this.front + 1) % this.capacity;
this.size--;
// 缩容
if (this.size <= this.capacity / 4 && this.capacity / 2 > 1) {
resize(this.capacity / 2);
}
return val;
}
public Optional<T> getFront() {
if (isEmpty()) {
return Optional.empty();
}
return Optional.of(this.data[this.front]);
}
// 测试
public static void main(String[] args) {
CycleArray<Integer> myArr = new CycleArray<>(5);
for (int i = 1; i <= 15; i++) {
myArr.addTail(i + 25);
System.out.println("添加:" + myArr);
if (i % 3 == 0) {
int val = myArr.removeHead();
System.out.println("删除: Header是:" + val);
}
}
}