week07_day01_自己实现LinkedList、MyStack

head 和 tail 是两个哨兵结点,不存储值。
在这里插入图片描述
在这里插入图片描述
MyList和MyIterator接口的代码和上节课一模一样

MyList:

package com.cskaoyan.list;

/**
 * @author shihao
 * @create 2020-05-15 17:28
 */

//想让MyArrayList和LinkedList也可以实现自己的foreach循环,
// 就得让MyList实现接口Iterable,表示有迭代的能力
public interface MyList<E> extends Iterable<E> {

    boolean add(E e);

    void add(int index, E e);

    void clear();

    boolean contains(Object obj);

    E get(int index);

    int indexOf(Object obj);

    boolean isEmpty();

    //MyIterator模仿的是listIterator
    //应当实现一个迭代器,对MyList进行遍历
    MyIterator<E> iterator();

    MyIterator<E> iterator(int index);

    int lastIndexOf(Object obj);

    E remove(int index);

    boolean remove(Object obj);

    E set(int index, E e);

    int size();
}

MyIterator:

package com.cskaoyan.list;

/**
 * @author shihao
 * @create 2020-05-16 8:09
 */

import java.util.Iterator;

//MyIterator模仿的是listIterator
//MyIterator
public interface MyIterator<E> extends Iterator<E> {
    boolean hasNext();

    boolean hasPrevious();

    E next();

    E previous();

    int nextIndex();

    int previousIndex();

    void add(E e);

    void remove();

    void set(E e);
}


MyLinkedList:

package com.cskaoyan.list;

import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * @author shihao
 * @create 2020-05-16 21:16
 */
public class MyLinkedList<E> implements MyList<E> {
    //属性
    //MyLinkedList底层是一个双端队列
    private Node head;
    private Node tail;
    private int size;
    private int modCount;
    //不需要默认容量和最大容量


    //Node不依赖于外部类对象而存在,所以将Node设置为static
    //当然,加上static后就不能将value设置为E类型,
    //因为泛型是创建对象的时候才把泛型参数传入进来的,泛型依赖于对象存在
    private static class Node {
        Node prev;
        Object value;
        Node next;

        public Node(Object value) {
            this.value = value;
        }

        public Node(Node prev, Object value, Node next) {
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    //构造方法
    //创建一个空链表
    public MyLinkedList() {
        head = new Node(null);
        tail = new Node(head, null, null);
        head.next = tail;
    }

    //应当在head之前和tail之后设置哨兵结点

    //方法

    /**
     * 在线性表最后添加元素
     *
     * @param e 待添加的元素
     * @return 如果添加成功返回true
     */
    @Override
    public boolean add(E e) {
        add(size, e);
        return true;
    }

    /**
     * 在线性表指定位置添加元素
     *
     * @param index 指定索引位置
     * @param e     待添加的元素
     */
    @Override
    public void add(int index, E e) {
        checkIndexForAdd(index);  //index的范围:[0,size]
        //需要考虑一种特殊情况:index == size时
        if (index == size) {
            Node nodeToAdd = new Node(tail.prev, e, tail);
            tail.prev.next = nodeToAdd;
            tail.prev = nodeToAdd;
        } else {
            //获取索引为index的结点
            Node node = getNode(index);  //index的范围:[0,size-1]
            //在node前面插入新节点
            Node nodeToAdd = new Node(node.prev, e, node);
            node.prev.next = nodeToAdd;
            node.prev = nodeToAdd;
        }

        size++;
        modCount++;
    }

    /**
     * 获取index位置的结点
     *
     * @param index
     * @return index位置的结点
     * <p>
     * A --> B --> C  size=3
     * A --> B --> C --> D  size=4
     */
    private Node getNode(int index) {
        if (index * 2 < size) {
            Node x = head.next;
            //x最终指向索引为index的结点
            for (int i = 0; i < index; i++) {
                x = x.next;
            }
            return x;
        } else {
            Node x = tail.prev;
            //x最终指向索引为index的结点
            for (int i = size - 1; i > index; i++) {
                x = x.prev;
            }
            return x;
        }
    }

    private void checkIndexForAdd(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("index = " + index + ", size = " + size);
        }
    }

    /**
     * 清空链表中所有元素
     */
    @Override
    public void clear() {
        head.next = tail;
        tail.prev = head;
        size = 0;
        modCount++;
    }

    /**
     * 判断线性表中是否有与指定元素相等的元素
     *
     * @param obj 指定对象
     * @return 如果存在这样额元素返回true,否则返回false
     */
    @Override
    public boolean contains(Object obj) {
        return indexOf(obj) != -1;
    }

    /**
     * 获取指定索引位置的元素
     *
     * @param index 指定索引位置
     * @return 指定索引位置的元素
     */
    @Override
    @SuppressWarnings("unchecked")
    public E get(int index) {
        checkIndex(index);
        return (E) getNode(index).value;
    }

    private void checkIndex(int index) {
        if (index < 0 || index > size - 1) {
            throw new IndexOutOfBoundsException("index = " + index + ", size = " + size);
        }
    }

    /**
     * 获取线性表中第一个与指定对象相等的元素
     *
     * @param obj 指定对象
     * @return 第一个和指定对象相等的元素的索引,如果不存在这样的索引返回-1
     */
    @Override
    public int indexOf(Object obj) {
        if (obj == null) {
            Node x = head.next;
            for (int i = 0; i < size; i++) {
                if (x.value == null) return i;
                x = x.next;
            }
        } else {
            Node x = head.next;
            for (int i = 0; i < size; i++) {
                if (obj.equals(x.value)) return i;
                x = x.next;
            }
        }
        return -1;
    }


    /**
     * 判断线性表是否为空
     *
     * @return 为空返回true,否则返回false
     */
    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 获取最后一个与指定对象相等元素的索引
     *
     * @param obj 指定对象
     * @return 最后一个与指定对象相等元素的索引,如果不存在这样的元素返回-1
     */
    @Override
    public int lastIndexOf(Object obj) {
        if (obj == null) {
            Node x = tail.prev;
            for (int i = size - 1; i >= 0; i--) {
                if (x.value == null) return i;
                x = x.prev;
            }
        } else {
            Node x = tail.prev;
            for (int i = size - 1; i >= 0; i--) {
                if (obj.equals(x.value)) return i;
                x = x.prev;
            }
        }
        return -1;
    }

    /**
     * 删除指定索引位置的元素,并把被删除的元素返回
     *
     * @param index 索引
     * @return 被删除的元素
     */
    @Override
    @SuppressWarnings("unchecked")
    public E remove(int index) {
        checkIndex(index);
        Node node = getNode(index);
        node.prev.next = node.next;
        node.next.prev = node.prev;
        size--;
        modCount++;
        return (E) node.value;
    }

    @Override
    public boolean remove(Object obj) {
        //不要用以下写法,因为indexOf会遍历一遍链表,remove(index)也会
        //遍历一遍链表,其实整个方法只需遍历一次链表即可,我们却遍历了两次
/*        int index = indexOf(obj);
        if (index == -1) return false;
        remove(index);
        return true;*/

        //只遍历一次
        if (obj == null) {
            Node x = head.next;
            for (int i = 0; i < size; i++) {
                if (x.value == null) {
                    //删除x结点
                    x.prev.next = x.next;
                    x.next.prev = x.prev;
                    size--;
                    modCount++;
                    return true;
                }
                x = x.next;
            }
        } else {
            Node x = head.next;
            for (int i = 0; i < size; i++) {
                if (obj.equals(x.value)) {
                    //删除x结点
                    x.prev.next = x.next;
                    x.next.prev = x.prev;
                    size--;
                    modCount++;
                    return true;
                }
                x = x.next;
            }
        }
        return false;
    }

    /**
     * 将索引位置元素替换为新值
     *
     * @param index 索引
     * @param e     新值
     * @return 旧值
     */
    @Override
    public E set(int index, E e) {
        checkIndex(index);
        Node node = getNode(index);
        E retValue = (E) node.value;
        node.value = e;
        return retValue;
    }

    /**
     * 获取线性表中元素的个数
     *
     * @return 元素的个数
     */
    @Override
    public int size() {
        return size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        Node x = head.next;
        while (x != tail) {
            sb.append(x.value).append("-->");
            x = x.next;
        }
        if (size != 0) {
            sb.delete(sb.length() - 3, sb.length());
        }
        return sb.append("]").toString();
    }

    /**
     * 获取迭代器,光标后面的元素的索引为0
     *
     * @return 迭代器
     */
    @Override
    public MyIterator<E> iterator() {
        return new Itr();
    }

    /**
     * 获取迭代器,光标后面的元素的索引为index
     *
     * @param index 光标后面的元素的索引
     * @return 迭代器
     */
    @Override
    public MyIterator<E> iterator(int index) {
        checkIndexForAdd(index);
        return new Itr(index);
    }

    private class Itr implements MyIterator<E> {
        //属性
        int cursor;  //光标后面元素的索引
        Node node;  //光标后面的结点
        int expModCount = modCount;  //期待被修改的次数
        //lastRet表示上一次返回的结点
        Node lastRet = null;  //null表示最近没有返回结点或最近返回的结点已失效

        //构造方法
        //无需加public,因为外界不可能通过构造方法访问到Itr内部类
        Itr() {
            node = head.next;
        }

        Itr(int index) {
            cursor = index;
            if (index == size) {
                node = tail;
            } else {
                node = getNode(index);
            }
        }

        //方法

        /**
         * 判断光标后面是否还有元素
         *
         * @return 如果有元素返回true,没有元素返回false
         */
        @Override
        public boolean hasNext() {
            return cursor != size;
        }

        /**
         * 判断光标前面是否还有元素
         *
         * @return 如果有元素返回true,没有元素返回false
         */
        @Override
        public boolean hasPrevious() {
            return cursor != 0;
        }

        /**
         * 将光标往后移动一个元素,并把被光标越过的元素返回
         *
         * @return 被光标越过的元素
         */
        @Override
        @SuppressWarnings("unchecked")
        public E next() {
            checkConModException();
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            cursor++;
            lastRet = node;
            node = node.next;
            return (E) lastRet.value;
        }

        private void checkConModException() {
            if (expModCount != modCount) {
                throw new ConcurrentModificationException();
            }
        }

        /**
         * 将光标往前移动一个位置,并把被光标越过的元素返回
         *
         * @return 被光标越过的元素
         */
        @Override
        @SuppressWarnings("unchecked")
        public E previous() {
            checkConModException();
            if (!hasPrevious()) {
                throw new NoSuchElementException();
            }
            cursor--;
            node = node.prev;
            lastRet = node;
            return (E) lastRet.value;
        }

        /**
         * 获取光标后面元素的索引
         *
         * @return
         */
        @Override
        public int nextIndex() {
            return cursor;
        }

        /**
         * 获取光标前面元素的索引
         *
         * @return
         */
        @Override
        public int previousIndex() {
            return cursor - 1;
        }

        /**
         * 在光标后面添加元素
         *
         * @param e 待添加的元素
         */
        @Override
        public void add(E e) {
            //不用这句代码,add(cursor,e)的时间复杂度为O(n)
            //MyLinkedList.this.add(cursor,e);
            //完全可以在O(1)的时间复杂度下完成add操作
            Node nodeToAdd = new Node(node.prev, e, node);
            node.prev.next = nodeToAdd;
            node.prev = nodeToAdd;
            size++;
            cursor++;
            lastRet = null;  //添加完元素后让最近返回的元素失效
            //如果没有这句代码,本迭代器修改之后,其他迭代器是感知不到修改的
            //也就是说理应报并发修改异常但却没报
            //解释:expModCount = ++modCount;后,本迭代器的expModCount和外部类中的modCount值相同
            //而在本迭代器创立之前的其他迭代器的expModCount可是比现在的++modCount小1,既然不相等
            //在执行it.next()时,调用 checkConModException();就会报并发修改异常
            expModCount = ++modCount;
        }

        /**
         * 删除最近返回的元素
         */
        @Override
        public void remove() {
            checkConModException();
            //当最近返回的元素失效或者最近没有返回的元素时
            if (lastRet == null) {
                throw new IllegalStateException();
            }
            //删除node
            lastRet.prev.next = lastRet.next;
            lastRet.next.prev = lastRet.prev;
            //4个属性值的变化
            expModCount = ++modCount;
            size--;
            //如果是逆向遍历,node和lastRet是相等的
            if (lastRet == node) {
                node = node.next;
            } else {  //如果是正向遍历,node和lastRet是不相等的
                cursor--;
            }
            lastRet = null;


        }

        /**
         * 替换最近返回的元素
         *
         * @param e 替换后的值
         */
        @Override
        public void set(E e) {
            checkConModException();
            if (lastRet == null) {
                throw new IllegalStateException();
            }
            lastRet.value = e;
            lastRet = null;
        }
    }

    public static void main(String[] args) {
        MyLinkedList<String> list = new MyLinkedList<>();
        System.out.println(list);
        list.add("hello");
        list.add("world");
        list.add("java");
        System.out.println(list);

        // void add(int index, E e)
        // list.add(0, "A");
        // list.add(1, "A");
        // list.add(list.size(), "A");
        // list.add(list.size() + 1, "A");
        // list.add(-1, "A");
        // System.out.println(list);

        // void clear(), int size(), boolean isEmpty()
        /*System.out.println(list);
        System.out.println(list.size());
        System.out.println(list.isEmpty());
        list.clear();
        System.out.println(list);
        System.out.println(list.size());
        System.out.println(list.isEmpty());*/

        // boolean contains(Object obj)
        /*System.out.println(list.contains("java")); //true
        System.out.println(list.contains("wuhan")); //false
        System.out.println(list.contains(null));//false
        list.add(null);
        System.out.println(list.contains(null));//true*/

        // int indexOf(Object obj)
/*        list.add("hello");
        System.out.println(list);
        System.out.println(list.indexOf("hello"));
        System.out.println(list.indexOf(null));
        list.add(0, null);
        list.add(null);
        System.out.println(list);
        System.out.println(list.indexOf(null));*/

        // int lastIndexOf(Object obj)
/*        list.add("hello");
        System.out.println(list);
        System.out.println(list.lastIndexOf("hello"));
        System.out.println(list.lastIndexOf(null));
        list.add(0, null);
        list.add(null);
        System.out.println(list);
        System.out.println(list.lastIndexOf(null));*/

        // E get(int index)
        // System.out.println(list.get(1));
        // System.out.println(list.get(-1));
        // System.out.println(list.get(list.size()));

        // E remove(index)
        // System.out.println(list.remove(1));
        // System.out.println(list.remove(-1));
        // System.out.println(list.remove(list.size()));
        // System.out.println(list);

        // boolean remove(Object)
        /*list.add("hello");
        System.out.println(list.remove("hello"));
        System.out.println(list);
        System.out.println(list.remove(null));
        System.out.println(list);
        list.add(0, null);
        list.add(null);
        System.out.println(list);
        System.out.println(list.remove(null));
        System.out.println(list);*/

        // E set(int index, E e)
        // System.out.println(list.set(2, "JAVA"));
        // System.out.println(list.set(-1, "JAVA"));
        // System.out.println(list.set(list.size(), "JAVA"));
        // System.out.println(list);

        /*****************************************************
         *                 Iterator
         *****************************************************/
//        MyLinkedList<String> list = new MyLinkedList<>();
//        list.add("hello");
//        list.add("world");
//        list.add("java");

        // boolean hasPrevious(), boolean hasNext()
        // MyIterator<String> it = list.iterator();
        // MyIterator<String> it = list.iterator(list.size());
        // MyIterator<String> it = list.iterator(1);
        // System.out.println(it.hasPrevious());
        // System.out.println(it.hasNext());

        // E previous(), E next()
        /*MyIterator<String> it = list.iterator();
        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());*/

/*        MyIterator<String> it = list.iterator(list.size());
        System.out.println(it.previous());
        System.out.println(it.previous());
        System.out.println(it.previous());
        System.out.println(it.previous());*/

        // int previousIndex()  int nextIndex()
        /*MyIterator<String> it = list.iterator();
        System.out.println(it.previousIndex());
        System.out.println(it.nextIndex());
        it.next();
        System.out.println(it.previousIndex());
        System.out.println(it.nextIndex());
        it.next();
        System.out.println(it.previousIndex());
        System.out.println(it.nextIndex());
        it.next();
        System.out.println(it.previousIndex());
        System.out.println(it.nextIndex());*/

        // void add(E e)
        /*MyIterator<String> it = list.iterator(1);
        it.add("A");
        it.add("B");
        it.add("C");
        System.out.println(list);
        System.out.println(it.next());*/

        // 在"hello"后面添加元素
        //测试两个迭代器的增加和遍历操作
//        MyIterator<String> iterator = list.iterator();
//        for (MyIterator<String> it = list.iterator(); it.hasNext(); ) {
//            String s = it.next();
//            if ("hello".equals(s)) {
//                int index = it.nextIndex();
//                it.add("A");
//            }
//        }
//        System.out.println(list);
//        //演示Itr中的add方法中的 expModCount = ++modCount; 这句代码的作用
//        while (iterator.hasNext()) {
//            String s = iterator.next();
//            System.out.println(s);
//        }


        // void remove()
        /*MyIterator<String> it = list.iterator();
        // it.remove();
        it.next();
        it.remove();
        System.out.println(list);*/
/*         MyIterator<String> it = list.iterator(list.size());
         it.previous();
         //it.add("HELLO");
         //add一次后lastRet所代表的最近返回的元素就失效了
         it.remove();
         System.out.println(list);
         //remove一次后lastRet所代表的最近返回的元素就失效了
         //it.remove();*/

        // 删除"hello"
        /*for(MyIterator<String> it = list.iterator(); it.hasNext(); ) {
            String s = it.next();
            if ("hello".equals(s)) {
                int index = it.previousIndex();
                list.remove(index);
            }
        }
        System.out.println(list);*/

/*        MyIterator<String> it = list.iterator();
        // it.set("HELLO");
        it.next();
        it.set("HELLO");
        // it.set("HeLLo");
        System.out.println(list);*/

        /*MyIterator<String> it = list.iterator(list.size());
        it.previous();
        it.set("JAVA");
        System.out.println(list);*/
    }

}

栈的非顺序映象(链栈):
在这里插入图片描述
····················································································································································································································

栈的API:

入栈 (push):在栈顶添加元素,O(1)
出栈 (pop):从栈顶删除元素,O(1)
查看栈顶元素 (peek):访问栈顶元素但不弹出,O(1)
判空 (isEmpty):判断栈是否为空, 方便遍历,O(1)

栈的非顺序映象(链栈):

package com.cskaoyan.stack;

import java.util.EmptyStackException;

/**
 * @author shihao
 * @create 2020-05-18 22:37
 * <p>
 * 栈的非顺序映象
 * API:
 * void push(E e)
 * E pop()
 * E peek()
 * boolean isEmpty()
 */
public class MyStack<E> {

    //使用单链表作为底层的数据结构
    private static class Node {
        Object value;
        Node next;

        public Node(Object value) {
            this.value = value;
        }

        public Node(Object value, Node next) {
            this.value = value;
            this.next = next;
        }
    }

    //属性
    private Node top;

    //构造方法
    //默认会实现无参构造方法,top会置为null

    //方法

    /**
     * 入栈,即在栈顶添加元素
     *
     * @param e 待添加的元素
     */
    public void push(E e) {
        top = new Node(e, top);
    }

    /**
     * 出栈,即删除栈顶元素
     * @return 删除掉的元素
     */
    @SuppressWarnings("unchecked")
    public E pop(){
        if (this.isEmpty()){
            throw new EmptyStackException();
        }
        E removeValue = (E) top.value;
        top = top.next;
        return removeValue;
    }

    /**
     * 查看栈顶元素
     * @return 栈顶元素
     */
    @SuppressWarnings("unchecked")
    public E peek(){
        if(this.isEmpty()){
            throw new EmptyStackException();
        }
        return (E) top.value;
    }

    /**
     * 判断栈是否为空
     *
     * @return 栈空返回true,否则返回false
     */
    public boolean isEmpty() {
        return top == null;
    }

}

栈的顺序映象(顺序栈):

package com.cskaoyan.stack;

import java.util.EmptyStackException;

/**
 * @author shihao
 * @create 2020-05-19 7:26
 * <p>
 * 栈的顺序映象
 * API:
 * void push(E e)
 * E pop()
 * E peek()
 * boolean isEmpty()
 */
public class MyStack02<E> {
    //栈的默认容量
    private static final int DEFAULT_CAPACITY = 10;
    //栈的最大容量
    private static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;

    //属性
    private Object[] elements;
    private int top = -1;

    //构造方法
    public MyStack02() {
        elements = new Object[DEFAULT_CAPACITY];
    }

    public MyStack02(int capacity) {
        if (capacity <= 0 || capacity > MAX_CAPACITY) {
            throw new IllegalArgumentException("capacity = " + capacity);
        }
        elements = new Object[capacity];
    }

    //方法

    /**
     * 入栈,即在栈顶添加元素
     *
     * @param e 待添加的元素
     */
    public void push(E e) {
        if (top == (elements.length - 1)) {
            //扩容
            int newLength = calculateCapacity();
            grow(newLength);
        }
        top++;
        elements[top] = e;
    }


    private void grow(int newCapacity) {
        //数组大小是不可变的,应当新建一个更大的数组,将原数组的元素传递给它
        Object[] newArr = new Object[newCapacity];
        for (int i = 0; i < elements.length; i++) {
            newArr[i] = elements[i];
        }

        //elements指向新数组
        elements = newArr;
    }

    private int calculateCapacity() {
        if (elements.length == MAX_CAPACITY) {
            throw new RuntimeException("Stack is too large!");
        }
        int newCapacity = elements.length + elements.length >> 1;
        if (newCapacity > MAX_CAPACITY || newCapacity < 0) {
            newCapacity = MAX_CAPACITY;
        }

        return newCapacity;
    }

    /**
     * 出栈,即删除栈顶元素
     *
     * @return 删除掉的元素
     */
    @SuppressWarnings("unchecked")
    public E pop() {
        if (top == -1) {
            throw new EmptyStackException();
        }
        E retValue = (E) elements[top];
        elements[top] = null;
        top--;
        return retValue;

    }

    /**
     * 查看栈顶元素
     *
     * @return 栈顶元素
     */
    @SuppressWarnings("unchecked")
    public E peek() {
        if (top == -1) {
            throw new EmptyStackException();
        }
        return (E) elements[top];
    }

    /**
     * 判断栈是否为空
     *
     * @return 栈空返回true,否则返回false
     */
    public boolean isEmpty() {
        return top == -1;
    }

}

练习题:反转字符串(要求用栈实现)
输入:“ABC”
输出:“CBA”
思路:
a.遍历字符串,获取每一个字符。charAt(int index)
b.将字符入栈
c.依次将字符出栈,并拼接

public class Demo01 {

    public static void main(String[] args) {
        String s = "123456";
        System.out.println(reverse(s));
    }

    private static String reverse(String original) {
        MyStack02<Character> myStack = new MyStack02<>();
        for (int i = 0; i < original.length(); i++) {
            char c = original.charAt(i);
            myStack.push(c);
        }
        StringBuilder sb = new StringBuilder();
        while (!myStack.isEmpty()) {
            sb.append(myStack.pop());
        }
        return sb.toString();
    }
}

应用场景:

  1. 函数调用栈:如在主方法中调用一个fun方法,会为fun方法创建一个栈帧,而一定是fun方法先执行结束的,然后主方法再执行结束。先调用的方法(主方法)后执行完,后调用的方法(fun方法)先执行完。这正好满足FILO特性。

  2. 括号匹配问题
    在这里插入图片描述
    老师代码:

public class StackDemo2 {
    public static void main(String[] args) {
        // String original = "([{}])";
        // String original = "()[]{";
        String original = "public static void main(String[ args) {System.out.println(bracketMatched(original));}";
        System.out.println(bracketMatched(original));
    }

    /*
    时间复杂度:O(n)
    空间复杂度:O(a):字符串中括号的个数
     */
    public static boolean bracketMatched(String original) {
        Deque<Character> stack = new LinkedList<>();
        // 遍历字符串, 获取每一个字符
        for (int i = 0; i < original.length(); i++) {
            char c = original.charAt(i);
            if (c == '(') stack.push(')');
            if (c == '[') stack.push(']');
            if (c == '{') stack.push('}');
            if (c == ')' || c == ']' || c== '}') {
                if (stack.isEmpty()) return false;
                if (c != stack.pop()) return false;
            }
        }
        // 遍历结束后
        return stack.isEmpty();
    }
}

我的代码(天勤、LeetCode之有效的括号):

class Solution {
    public boolean isValid(String s) {
        char[] stack=new char[s.length()];
        int top=-1;

        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            if(ch=='('||ch=='['||ch=='{')
                stack[++top]=ch;
            else{
                if(top==-1)
                    return false;       //缺左括号
                char left=stack[top--];
                if(!isMathced(left,ch))
                    return false;       //左右括号不匹配
            }
        }
        if(top!=-1)
            return false;     //缺右括号
        return true;
    }

    private boolean isMathced(char left,char right){
        if(left=='('&&right==')')
            return true;
        else if(left=='['&&right==']')
            return true;
        else if(left=='{'&&right=='}')
            return true;
        else
            return false;
    }
}
  1. 编译器利用栈实现表达式求值
    在这里插入图片描述
    具体代码看之前天勤笔记。

  2. 浏览器的前进后退功能
    在这里插入图片描述

  3. 利用栈实现 DFS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-玫瑰少年-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值