栈的顺序存储结构
定义
栈是限定仅在表尾进行插入和删除的线性表【后进先出,简称LIFO结构】
栈顶:允许插入和删除的一段
栈底:另一端
空栈:不包含任何数据元素的栈称为空栈
栈本身是一个线性表,其数据元素具有线性关系,只不过它是一种特殊的线性表
栈的插入操作,叫做进栈,也称压栈,入栈
栈的删除操作,叫做出栈,也称弹栈
栈的实现
- 使用链式结构
使用单链表,通过在表的顶端插入来实现push,通过删除表顶端元素实现pop,top操作只是在读取其栈顶的值并进行返回。 - 使用数组
栈接口stack的定义
package DS01;
/*
线性表的一种特殊情况 栈
ArrayStack extends ArrayList
ArrayList当做是ArraySatck的一个成员变量
*/
public interface Stack<E> extends Iterable<E>{
//获取栈中元素的个数
int getSize();
//判断栈是否为空
boolean isEmpty();
//将元素e进栈
void push(E e);
//弹栈一个元素并返回
E pop();
//查看当前栈顶元素
E peek();
//清空栈
void clear();
}
栈的顺序存储结构ArrayStack的定义
在原有list的顺序存储基础上,写stack
package DS01;
import java.util.Iterator;
/*顺序栈内部是由顺序表实现的
* ArrayStack
* ArrayList
* */
public class ArrayStack<E> implements Stack<E> {
private ArrayList<E> list;
//创建一个默认大小的栈
public ArrayStack(){
list=new ArrayList<>();
}
//创建一个指定大小的栈
public ArrayStack(int capacity){
list=new ArrayList<>(capacity);
}
@Override
public int getSize() {
return list.getSize();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void push(E e) {
list.addLast(e);
}
@Override
public E pop() {
return list.removeLast();
}
@Override
public E peek() {
return list.getLast();
}
@Override
public void clear() {
list.clear();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append(String.format("ArrayStack: %d/%d\n",getSize(),list.getcapactiy()));
sb.append('[');
if(isEmpty()){
sb.append(']');
}else{
for(int i=0;i<getSize();i++){
sb.append(list.get(i)); //无法直接访问date数组,调用get函数
if(i==getSize()-1){
sb.append(']');
}else{
sb.append(',');
}
}
}
return sb.toString();
}
}
编写主函数
package DS01;
import java.util.Iterator;
public class TestArrayStack {
public static void main(String[] args) {
ArrayStack<Integer> stack=new ArrayStack<>();
System.out.println(stack);
for(int i=1;i<=15;i++){
stack.push(i);
}
System.out.println(stack);
for(int i=1;i<=10;i++){
stack.pop();
}
System.out.println(stack);
for(Integer i:stack){
System.out.print(i+" ");
}
Iterator<Integer> it=stack.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
}
}
执行结果
双端栈的顺序存储结构
定义
是将一个线性表的两端当做栈底分别进行入栈和出栈操作
定义两个指针,leftTop与rightTop
在进行入栈操作时:左边的栈顶是leftTop的右边,右边的栈顶是rightTop的左边【先移动指针,后将值赋给指针所在的位置】
出栈操作时:在栈顶进行指针移动,移出元素,指针减一
双端栈的顺序存储结构ArrayStackDoubleEnd的定义
package DS01;
import java.util.Iterator;
//双端栈
class ArrayStackDoubleEnd<E> implements Stack<E> {
private E[] data;
//定义方向
private int lefttop;
private int righttop;
//定义默认长度
private static final int DESAULT_SIZE=10;
//默认构造函数
ArrayStackDoubleEnd(){
this(DESAULT_SIZE);
}
//默认有参数的构造函数
private ArrayStackDoubleEnd(int capacity){
data=(E[])(new Object [capacity]);
lefttop=-1;
righttop=data.length;
}
获取双端栈中有限元素的得个数
//获取左边栈中有效元素的个数
public int getleftSize(){
return lefttop+1;
}
//获取右边栈中有效元素的个数
public int getrigthSize(){
return data.length-righttop;
}
//获取栈中所有元素的个数
public int getSize(){
return getleftSize()+getrigthSize();
}
判断双端栈中是否为空
//判断左栈是否为空
public boolean isleftEmpty(){
return lefttop==-1;
}
//判断右栈是否为空
public boolean isrightEmpty(){
return righttop==data.length;
}
//判断栈是否为空
public boolean isEmpty(){
return isrightEmpty()&&isrightEmpty();
}
元素的进栈操作
//在左栈进栈
public void pushLeft(E e){
if(lefttop+1==righttop){ //判定是否栈满
resize(2*data.length); //扩容
}
//进栈
lefttop++;
data[lefttop]=e;
}
//在右边进栈
public void pushRight(E e){
if(lefttop+1==righttop){
resize(2*data.length);
}
righttop--;
data[righttop]=e;
}
扩容操作
//扩容
private void resize(int newlen) {
E[] newdata=(E[])(new Object[newlen]);
for (int i = 0; i < lefttop; i++) {
newdata[i]=data[i];
}
for (int i = righttop; i < data.length; i++) {
newdata[i+data.length]=data[i];
}
righttop=righttop+data.length;
data=newdata;
}
进栈操作
//进栈元素
public void push(E e){
//if(lefttop<=righttop)
if(Math.random()>=0.5){
pushLeft(e);
}else{
pushRight(e);
}
}
弹栈操作
//左边弹栈
private E popLeft(){
if(isleftEmpty()){
throw new IllegalArgumentException("左栈为空");
}
E ret =data[lefttop];
if(getSize()<=data.length/4&&data.length/2>10){
resize(data.length*2);
}
return data[lefttop--];
}
//右边弹栈
private E popright(){
if(isrightEmpty()){
throw new IllegalArgumentException("右栈为空");
}
return data[righttop++];
}
//弹栈
public E pop(){
if(getrigthSize()>=getleftSize()){
popright();
}else{
popLeft();
}
return null;
}
读取栈顶元素
//读取左边的栈顶元素
public E peekleft(){
if(isleftEmpty()){
throw new IllegalArgumentException("左栈为空");
}
return data[lefttop];
}
//读取右边的栈顶元素
public E peekright(){
if(isleftEmpty()){
throw new IllegalArgumentException("右栈为空");
}
return data[righttop];
}
//读取栈顶元素
public E peek(){
if(getleftSize()>=getrigthSize()){
return peekright();
}else{
return peekleft();
}
}
清空双端栈
public void clear(){
data=(E[])(new Object[DESAULT_SIZE]);
lefttop=-1;
righttop=data.length;
}
字符串输出
public String toString(){
StringBuilder sb =new StringBuilder();
sb.append(String.format("ArrayStackDoubleEnd:%d,%d\n",getSize(),data.length));
if(isleftEmpty()) {
sb.append("left :bottom [] top\n");
}else {
sb.append("left :bottom [");
for (int i = 0; i <= lefttop; i++) {
sb.append(data[i]);
if(i==lefttop){
sb.append("] top");
}else{
sb.append(',');
}
}
}
sb.append('\n');
if(isrightEmpty()){
sb.append("right:top [] bootom\n");
}else {
sb.append("right:top [");
for(int i=righttop;i<data.length;i++){
sb.append(data[i]);
if(i==data.length-1){
sb.append("] bottom");
}else{
sb.append(',');
}
}
}
return sb.toString();
}
迭代器
@Override
public Iterator iterator() {
return null;
}
}
双端栈测试
package DS01;
public class TestArrayStackDoubleEnd {
public static void main(String[] args) {
ArrayStackDoubleEnd<Integer> stack=new ArrayStackDoubleEnd<>();
System.out.println(stack);
for(int i=1;i<=6;i++){
stack.pushLeft(i);
}
for(int i=1;i<=6;i++){
stack.pushRight(i);
}
System.out.println(stack);
for(int i=1;i<=8;i++){
System.out.print(stack.pop()+" ");
}
System.out.println();
System.out.println(stack);
}
}
输出结果