一、栈的简单介绍
1、栈是一种线性结构。我们可以通过数组和链表实现。它依赖的原则是先进后出的原则。
2、栈可以实现括号匹配,表示式计算等功能。
3、我们在在平常的函数调用中,都可能用到栈和队列。
二、栈的数组实现方式。
1、利用我们前面学的动态数组的实现方式。
package com.ypl.demo;
public interface Array<T> {
public int getCapciaty();
public int getSize();
public boolean isEmpty();
public void add(int index, T element);
public void addFirst( T element);
public void addLast(T element);
public T get(int index);
public void set(int index,T element);
public void print();
public boolean contains(T element);
public int find(T element);
public T remove(int index);
public T removeFirst();
public T removeLast();
public void removeElement(T element);
public T getLast();
}
package com.ypl.demo;
/**
* 实现一个动态数组
*
* @author ypl
*/
public class ArrayImpl<T> implements Array<T> {
private int size; // 表示的是数组的大小
private T[] data; // 定义一个数组
public ArrayImpl(int capciaty) {
data = (T[]) new Object[capciaty]; // 创建一个数组
size = 0;
}
public ArrayImpl() {
this(10);
}
/**
* 获取数组的容量
*
* @return
*/
@Override
public int getCapciaty() {
return data.length;
}
/**
* 获取数组的大小
*
* @return
*/
@Override
public int getSize() {
return size;
}
/**
* 判断数组是否为空
*
* @return
*/
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* 向数组的指定位置添加元素。
*
* @param index
* @param element
*/
@Override
public void add(int index, T element) {
// 2、判断是否为满
if (size == data.length) {
resize(size*2); //进行扩容操作
}
// 2、判断index 是否合法。
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is illegal");
}
// 3、进行插入操作
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
// 4、进行赋值插入
data[index] = element;
// 5、元素个数加1
size++;
}
private void resize(int index) {
T [] data2=(T[]) new Object[index];
for(int i=0;i<size;i++){ //进行赋值操作
data2[i]=data[i];
}
data=data2;
}
/**
* 在数组的头部插入元素
*/
@Override
public void addFirst(T element) {
add(0, element);
}
/**
*
* 在数组中的尾部插入元素
*/
@Override
public void addLast(T element) {
add(size, element);
}
/**
* 获取index索引位置的元素
*
* @param index
* @return
*/
@Override
public T get(int index) {
// 1、判断index 是否合法。
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index is illegal");
}
return data[index];
}
/**
* 修改index索引位置的元素为e
*
* @param index
* @param element
*/
@Override
public void set(int index, T element) {
// 1、判断index 是否合法。
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index is illegal");
}
data[index] = element;
}
// 查找数组中是否有元素e
/**
* 显示所有的数组元素
*/
@Override
public void print() {
for (int i = 0; i < size; i++) {
System.out.println(data[i]);
}
}
/**
* 查找数组中是否有元素e
*/
@Override
public boolean contains(T e) {
for (int i = 0; i < size; i++) {
if (e.equals(data[i])) {
return true;
}
}
return false;
}
/**
* 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
*/
@Override
public int find(T e) {
for (int i = 0; i < size; i++) {
if (e.equals(data[i])) {
return i;
}
}
return -1;
}
/**
* 从数组中删除index位置的元素, 返回删除的元素
*/
@Override
public T remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index is illegal");
}
T res = data[index]; // 获取结果
for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i]; // data[index]
}
size--;
if(size == data.length/4 && data.length/2!=0) resize(data.length/2); //如果元素的个数小于容量的1/4 ,我们就进行缩容操作 到容量的1/2
return res;
}
/**
* 从数组中删除第一个元素, 返回删除的元素
*/
@Override
public T removeFirst() {
T res = remove(0);
return res;
}
/**
* 从数组中删除最后一个元素, 返回删除的元素
*/
@Override
public T removeLast() {
T res = remove(size - 1);
return res;
}
/**
* 从数组中删除元素e
*/
@Override
public void removeElement(T element) {
int index = find(element);
if (index != -1) {
remove(index);
}
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));
res.append('[');
for (int i = 0; i < size; i++) {
res.append(data[i]);
if (i != size - 1)
res.append(", ");
}
res.append(']');
return res.toString();
}
@Override
public T getLast() {
// TODO Auto-generated method stub
return get(size-1);
}
}
2、实现栈的声明和实现。
package com.ypl.demo;
public interface Stack<E> {
int getSize();
boolean isEmpty();
void push(E e);
E pop();
E peek();
}
package com.ypl.demo;
public class ArrayStack<E> implements Stack<E> {
private Array<E> array;
public ArrayStack() {
array=new ArrayImpl<E>();
}
public ArrayStack(int capciaty) {
array=new ArrayImpl<E>(capciaty);
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return array.getSize();
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return array.getSize()==0;
}
@Override
public void push(E e) { //从数组后面插入
array.addLast(e);
}
@Override
public E pop() { //从数组尾部弹出
// TODO Auto-generated method stub
return array.removeLast();
}
@Override
public E peek() { //从数组尾部获取
// TODO Auto-generated method stub
return array.getLast();
}
}
三、总结
1、栈在函数调用中的应用。
2、栈在表达式求值得应用。
3、栈在括号匹配中的应用。
这些都是我们应该掌握和学习的东西。并且我们能够用白纸可以写出栈的实现代码。