使用stack实现浏览器的页面的前进后退

//===========================测试代码============================

public class Main {
    public static void main(String[] args) {
        MyStack<String> oldStack = new MyStack<>();
        MyStack<String> newStack = new MyStack<>();
        oldStack.push("百度");
        oldStack.push("淘宝");
        oldStack.push("腾讯");
        MyStack<String> click = new MyStack<>();
        click.back(oldStack, newStack);//退到淘宝
        click.back(oldStack, newStack);//退到百度
        click.insertNewPage("拼多多", oldStack, newStack);
        System.out.println(oldStack.list.toString());
        click.back(oldStack, newStack);//退到百度
        click.go(oldStack, newStack);//拼多多
        System.out.println(oldStack.list.toString());
    }

}

//===============================stack================================

package com.fine.stack;

import com.fine.List;
import com.fine.list.MyArrayList;

/**
 * @description: 后进先出
 * @author:
 * 接口设计: size 入栈 出栈 清空 获取栈顶元素 是否为空
 */
public class MyStack<E> {
   public  List<E> list = new MyArrayList();

    /**
     * 入栈
     *
     * @param element
     */
    public void push(E element) {
        list.add(element);
    }

    /**
     * 出栈
     *
     * @return
     */
    public E pop() {
        //删除栈顶元素
        return list.remove(list.size() - 1);
    }

    /**
     * 获取栈顶元素
     */
    public E getTop() {
        return list.get(list.size() - 1);
    }

    /**
     * 模拟浏览器页面前进、后退、进入新页面
     */
    public void go(MyStack<E> oldStack, MyStack<E> newStack) {
        if (newStack.list.size() > 0) {
            E pop = newStack.pop();
            oldStack.push(pop);
            System.out.println("前进到" + oldStack.getTop().toString());
        } else {
            System.out.println("已经最前面了");
        }

    }

    public void back(MyStack<E> oldStack, MyStack<E> newStack) {
        if (oldStack.list.size() > 0) {
            E pop = oldStack.pop();
            newStack.push(pop);
            System.out.println("回退到" + oldStack.getTop().toString());
        } else {
            System.out.println("已经最后一页了");
        }

    }

    public void insertNewPage(E element, MyStack<E> oldStack, MyStack<E> newStack) {
        oldStack.push(element);
        newStack = new MyStack<>();
    }
}

//=======================MyArrayList==========================

package com.fine.list;


import com.fine.AbstractList;

@SuppressWarnings("unchecked")
public class MyArrayList<E> extends AbstractList<E> {

    /**
     * 所有的元素
     */
    private E[] elements;

    public MyArrayList() {
        this(DEFAULT_CAPACITY);
    }

    public MyArrayList(int capacity) {
        if (capacity > 0) {
            elements = (E[]) new Object[capacity];
        } else {
            /**
             *1.a:创建一定容量的新数组,内存会分配连续的字节(内存地址),如果数组是int类型,则一共分配了4*10个字节
             *  b:移除元素时,由于内存地址是连续的,所以不能把要移除地方全部删掉,内存不支持这种操作,只有元素往前挪
             *2.a:针对应用类型,创建数组在堆开辟内存空间,每一个元素真正的数据再重新开辟空间,数组上存的是元素的内存地址值,不是直接存对应上元素,
             *    如果数组直接存对象,该位置的对象大小是动态的,所以直接存地址更好,也更节省空间,比如数组默认长度10,一个对象10个字节,就需要100个字节,但如果存地址就无需开辟这么多
             *  b:针对基本类型,数组上直接存值
             *3.a:内存空间如何销毁
             *    直接清除数组上的內存地址
             *
             */
            elements = (E[]) new Object[DEFAULT_CAPACITY];
        }
    }

    /**
     * 清除所有元素
     */
    public void clear() {
        for (int index = 0; index < size; index++) {
            elements[index] = null;
        }
        size = 0;
    }

    /**
     * 是否包含某个元素
     *
     * @param element
     * @return
     */
    public boolean contains(E element) {
        boolean result = false;
        for (int index = 0; index < size; index++) {
            if (elements[index].equals(element)) {
                result = true;
            }
        }
        return result;
    }

    /**
     * 添加元素到尾部
     *
     * @param element
     */
    public void add(E element) {
        if (size < elements.length) {
            this.addIndex(size, element);
        } else {
            //扩容再添加
            this.ensureCapacity(size + 1);
            this.addIndex(size, element);
        }
    }

    /**
     * 在index位置插入一个元素
     * 在指定位置插入,后面位置的元素向后挪动,如果超出了索引范围就追加在最后面,索引小于0加在最前面
     *
     * @param index
     * @param element
     */
    public void addIndex(int index, E element) {
        this.rangeCheckForAdd(index);
        if (index < 0) {
            index = 0;
        }
        for (int i = size - 1; i >= index; i--) {
            if (i + 1 <= elements.length - 1) {
                elements[i + 1] = elements[i];
            } else {
                this.ensureCapacity(size + 1);
                elements[i + 1] = elements[i];
            }
        }
        if (index >= elements.length) {
            this.ensureCapacity(size + 1);
        }
        elements[index] = element;
        ++size;
    }

    /**
     * 获取index位置的元素,访问时间和下标没有关系
     * 不管取索引是多少的元素复杂度都是O(1),因为底层是直接解析nums[index]算出地址,通过地址去找元素
     *
     * @param index
     * @return
     */
    public E get(int index) {
        this.rangeCheck(index);
        return elements[index];
    }

    /**
     * 设置index位置的元素
     *
     * @param index
     * @param element
     * @return 原来的元素ֵ
     */
    public E set(int index, E element) {
        this.rangeCheck(index);
        E old = elements[index];
        elements[index] = element;
        return old;
    }

    /**
     * 删除index位置的元素
     * 删除一个元素其实是改为元素的后一个元素向前覆盖
     *
     * @param index
     * @return 成功移除的元素, 失败抛异常
     */
    public E remove(int index) {
        this.rangeCheck(index);
        E oldEle = elements[index];
        //移动元素
        for (int i = index; i < size - 1; i++) {
            elements[i] = elements[i + 1];
        }
        //最后一个元素
        elements[--size] = null;
        if (elements.length >> 2 >= size && elements.length > DEFAULT_CAPACITY) {
            tirm();
        } else {
            return oldEle;
        }
        return oldEle;
    }

    /**
     * 缩容
     */
    private void tirm() {
        int oldCapacity = elements.length;
        int newCapacity = oldCapacity >> 1;
        E[] newElements = (E[]) new Object[newCapacity];
        for (int index = 0; index < size; index++) {
            newElements[index] = elements[index];
        }
        elements = newElements;
        System.out.println(oldCapacity + "缩容为" + newCapacity);
    }

    /**
     * 查看元素的索引
     *
     * @param element
     * @return
     */
    public int indexOf(E element) {
        if (element == null) {
            for (int index = 0; index < size; index++) {
                if (elements[index] == null) return index;
            }
        } else {
            for (int index = 0; index < size; index++) {
                if (elements[index].equals(element)) return index;
            }
        }
        return ELEMENT_NOT_FOUND;
    }

    /**
     * 保证要有capacity的容量
     * 不允许在老数组后面申请新的内存空间,只有重新开辟一块新空间,把老数据加进去
     *
     * @param capacity
     */
    private void ensureCapacity(int capacity) {
        int oldCapacity = elements.length;
        if (oldCapacity >= capacity) {
            return;
        }
        //浮点数的计算比整数计算更耗时间,所以这里不用浮点数计算
        //double newCapacityDoub = oldCapacity * 1.5; >>1 = /2 ;<<1 = *2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        E[] newElements = (E[]) new Object[newCapacity];
        for (int index = 0; index < size; index++) {
            newElements[index] = elements[index];
        }
        elements = newElements;
        System.out.println(oldCapacity + "扩容为" + newCapacity);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("size=" + size + ":[");
        if (size == 0) {
            sb.append("]");
        } else {
            for (int i = 0; i < size; i++) {
                if (i == (size - 1)) {
                    sb.append(elements[i] + "]");
                } else {
                    sb.append(elements[i] + ",");
                }
            }
        }
        return new String(sb);
    }
}

//=============================AbstractList================================

package com.fine;

/**
 * 抽象类可以不实现接口的方法
 * 此类不对外公开,负责封装公共方法
 * @param <E>
 */
public abstract class AbstractList<E> implements List<E> {
    /**
     * 元素的数量
     */
    protected int size;

    /**
     * 元素的数量
     *
     * @return
     */
    public int size() {
        return size;
    }

    /**
     * 是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    public void outOfBounds(int index) {
        throw new IndexOutOfBoundsException("index=" + index + ",size=" + size);
    }

    public void rangeCheck(int index) {
        if (index < 0 || index >= size) {
            this.outOfBounds(index);
        }
    }

    public void rangeCheckForAdd(int index) {
        if (index < 0 || index > size) {
            this.outOfBounds(index);
        }
    }
}

 

//============================List接口==============================

package com.fine;

public interface List<E> {

    public static final int DEFAULT_CAPACITY = 2;

    public static final int ELEMENT_NOT_FOUND = -1;
    /**
     * 清除所有元素
     */
    public void clear();

    /**
     * 是否包含某个元素
     *
     * @param element
     * @return
     */
    public boolean contains(E element);

    /**
     * 添加元素到尾部
     *
     * @param element
     */
    public void add(E element);

    /**
     * 在index位置插入一个元素
     * @param index
     * @param element
     */
    public void addIndex(int index, E element);

    /**
     * 获取index位置的元素
     *
     * @param index
     * @return
     */
    public E get(int index);

    /**
     * 设置index位置的元素
     *
     * @param index
     * @param element
     * @return 原来的元素ֵ
     */
    public E set(int index, E element);

    /**
     * 删除index位置的元素
     * @param index
     * @return 成功移除的元素, 失败抛异常
     */
    public E remove(int index);

    /**
     * 查看元素的索引
     *
     * @param element
     * @return
     */
    public int indexOf(E element);

    /**
     * 元素的数量
     *
     * @return
     */
    public int size();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值