02 栈(Stack)

栈是一种后进先出的数据结构(Last In First Out, LIFO),本文将以数组实现栈的数据结构。

1.栈的接口

 1 /**
 2  * @author 阿遠
 3  * Date: 2019/1/14
 4  * Time: 10:37
 5  */
 6 public interface Stack<E> {
 7 
 8     int getSize(); // 查看栈的容量
 9     boolean isEmpty(); // 判断栈非空
10     void push(E e); // 入栈
11     E pop(); // 出栈
12     E peek(); // 查看栈顶元素
13 }
Stack

2.栈的接口的数组实现

  1 /**
  2  * @author 阿遠
  3  * Date: 2019/1/13
  4  * Time: 19:29
  5  */
  6 // 数组操作接口的实现
  7 public class Array<E> {
  8 
  9     private E[] data;
 10     private  int size; // 数组中实际元素数量
 11 
 12     // 构造函数,传入数组的容量capacity构造Array
 13     public Array(int capacity) {
 14         data = (E[]) new Object[capacity];
 15         size = 0;
 16     }
 17     // 默认构造函数,默认数组的容量capacity=10
 18     public Array() {
 19         this(10);
 20     }
 21     // 获取数组中的容量
 22     public int getCapacity() {
 23         return data.length;
 24     }
 25     //获取数组的元素个数
 26     public int getSize() {
 27         return size;
 28     }
 29     // 判断数组是否为空
 30     public boolean isEmpty() {
 31         return size == 0;
 32     }
 33     // 向所有元素后添加一个新元素
 34     public void addLast(E e) {
 35 //        if (size == data.length){
 36 //            throw new IllegalArgumentException("addLast failed!Array is full");
 37 //        }
 38 //        data[size] = e;
 39 //        size++;
 40         // 复用add
 41         add(size, e);
 42     }
 43     //在所有元素前添加新元素
 44     public void addFirst(E e) {
 45         add(0, e);
 46     }
 47     // 在index个位置插入一个新元素,扩容成动态数组,此处我们扩容成原来的2倍,在ArrayList中为1.5倍
 48     public void add(int index, E e) {
 49 
 50         if (index < 0 || index > size) {
 51             throw new IllegalArgumentException("Add failed!Index required >=0 and <size");
 52         }
 53         if (size == data.length){
 54             resize(2 * data.length);
 55         }
 56         for (int i = size-1; i >= index; i--){
 57             data[i+1] = data[i];
 58         }
 59         data[index] = e;
 60         size ++;
 61     }
 62     // 给数组扩容或者缩容
 63     private void resize(int newCapacity) {
 64         E[] newData = (E[]) new  Object[newCapacity];
 65         for (int i = 0; i < size; i++) {
 66             newData[i] = data[i];
 67         }
 68         data = newData;
 69     }
 70     // 获取index索引位置的元素
 71     public E get(int index) {
 72         if (index < 0 || index > size) {
 73             throw new IllegalArgumentException("Get failed!Index is illegal.");
 74         }
 75         return data[index];
 76     }
 77     // 获取数组第一个元素
 78     public E getFirst() {
 79         return get(0);
 80     }
 81     // 获取数组最后一个元素
 82     public E getLast() {
 83         return get(size-1);
 84     }
 85     //修改index元素索引位置的元素为e
 86     public void  set(int index, E e) {
 87         if (index < 0 || index > size) {
 88             throw new IllegalArgumentException("Set failed!Index is illegal.");
 89         }
 90         data[index] = e;
 91     }
 92 
 93     @Override
 94     public  String toString() {
 95         StringBuilder res = new StringBuilder();
 96         res.append(String.format("Array: size = %d, capacity = %d
", size, data.length));
 97         res.append("[");
 98         for (int i = 0; i < size; i++) {
 99             res.append(data[i]);
100             if (i != size-1)
101                 res.append(", ");
102         }
103         res.append("]");
104         return res.toString();
105     }
106 
107     // 查找数组中是否存在元素e
108     public boolean contains(E e) {
109         for (int i= 0; i < size; i++) {
110             if (data[i] == e)
111                 return true;
112         }
113         return false;
114     }
115     // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
116     public int find(E e) {
117         for (int i = 0; i < size; i++) {
118             if (data[i] == e)
119                 return  i;
120         }
121         return -1;
122     }
123     // 从数组中删除元素,返回删除的元素
124     public E remove(int index) {
125         if (index < 0 || index >= size) {
126             throw new IllegalArgumentException("Remove failed!Index is illegal.");
127         }
128         E ret = data[index];
129         for (int i = index + 1; i < size; i++) {
130             data[i-1] = data[i];
131         }
132         size --;
133         data[size] = null; // loitering objects != memory leak
134         if (size == data.length/4 && data.length/2 != 0) {
135             resize(data.length/2);
136         }
137         return ret;
138     }
139     // 从数组中删除第一个元素
140     public E removeFirst() {
141         return remove(0);
142     }
143     // 从元素中删除最后一个元素
144     public E removeLast() {
145         return remove(size-1);
146     }
147     // 从数组中删除元素e
148     public void removeElement(E e) {
149         int index = find(e);
150         if (index != -1) {
151             remove(index);
152         }
153     }
154 }
Array
 1 /**
 2  * @author 阿遠
 3  * Date: 2019/1/14
 4  * Time: 10:39
 5  */
 6 public class ArrayStack<E> implements Stack<E> {
 7 
 8     // 基于动态数组实现的栈结构
 9     Array<E> array;
10 
11     public  ArrayStack(int capacity) {
12         array = new Array<E>(capacity);
13     }
14 
15     public ArrayStack() {
16         array = new Array<E>();
17     }
18 
19     // 获取数组容量
20     public int getCapacity() {
21         return array.getCapacity();
22     }
23 
24     // 获取数组元素个数
25     @Override
26     public int getSize() {
27         return array.getSize();
28     }
29 
30     // 非空判断
31     @Override
32     public boolean isEmpty() {
33         return array.isEmpty();
34     }
35 
36     // 入栈
37     @Override
38     public void push(E e) {
39         array.addLast(e);
40     }
41 
42     // 出栈
43     @Override
44     public E pop() {
45         return array.removeLast();
46     }
47 
48     // 取出栈顶元素
49     @Override
50     public E peek() {
51         return array.getLast();
52     }
53 
54     @Override
55     public String toString() {
56         StringBuilder res = new StringBuilder();
57         res.append("Stack:");
58         res.append("[");
59          for (int i = 0; i < array.getSize(); i++){
60              res.append(array.get(i));
61              if (i != array.getSize()-1) {
62                  res.append(", ");
63              }
64          }
65         res.append("] top");
66          return res.toString();
67     }
68 }
ArrayStack

 2.1测试

 1 public class Main {
 2 
 3     public static void main(String[] args) {
 4 
 5         ArrayStack<Integer> stack = new ArrayStack<Integer>();
 6 
 7         for (int i = 0; i < 5; i++) {
 8             stack.push(i);
 9         }
10         System.out.println(stack);
11         stack.pop();
12         System.out.println("出栈:");
13         System.out.println(stack);
14     }
15 }

 2.2测试结果:

Stack:[0, 1, 2, 3, 4] top
出栈:
Stack:[0, 1, 2, 3] top

3.栈的接口的链表实现

  1 /**
  2  * @author 阿遠
  3  * Date: 2019/1/15
  4  * Time: 11:08
  5  */
  6 public class LinkedList<E> {
  7 
  8 
  9     private Node dummyhead; // 链表头
 10     private int size; // 链表容量
 11     private class Node{
 12         public E e;  // 元素
 13         public Node next;   // 结点
 14 
 15         private Node(E e, Node next) {
 16             this.e = e;
 17             this.next = next;
 18         }
 19 
 20         public Node(E e) {
 21             this(e, null);
 22         }
 23 
 24         public Node() {
 25             this(null, null);
 26         }
 27 
 28         @Override
 29         public String toString() {
 30             return e.toString();
 31         }
 32     }
 33 
 34     public LinkedList() {
 35         dummyhead = new Node(null, null);
 36         size = 0;
 37     }
 38 
 39     // 获取列表中的元素个数
 40     public int getSize() {
 41         return size;
 42     }
 43 
 44     // 返回链表是否为空
 45     public boolean isEmpty() {
 46         return size == 0;
 47     }
 48 
 49     //在链表的index(0-based)位置添加新的元素e
 50     public void add(int index, E e) {
 51         if (index < 0 || index > size) {
 52             throw new IllegalArgumentException("Add failed.Illegal index.");
 53         }
 54         Node pre = dummyhead;
 55         for (int i = 0; i < index; i ++) {
 56             pre = pre.next;
 57         }
 58 //            Node node = new Node(e);
 59 //            node.next = pre.next;
 60 //            pre.next = node;
 61         pre.next = new Node(e, pre.next);
 62         size ++;
 63     }
 64     //在链表头添加新的元素
 65     public void addFirst(E e) {
 66         add(0, e);
 67     }
 68     // 在链表的末尾添加新的元素
 69     public void addLast(E e) {
 70         add(size, e);
 71     }
 72 
 73     // 获得链表的第index个位置的元素
 74     public E get(int index) {
 75         if (index < 0 || index >= size)
 76             throw new IllegalArgumentException("Get failed.Illegal index.");
 77         Node cur = dummyhead.next;
 78         for (int i = 0; i < index; i++) {
 79             cur = cur.next; // 遍历找到index处的Node
 80         }
 81         return cur.e;
 82     }
 83     // 获得列表的第一个元素
 84     public E getFirst() {
 85         return get(0);
 86     }
 87     // 获得链表中最后一个元素
 88     public E getLast() {
 89         return get(size - 1);
 90     }
 91 
 92     // 修改列表中第index个位置的元素为e
 93     public void set(int index, E e) {
 94         if (index < 0 || index >= size)
 95             throw new IllegalArgumentException("Update failed.Illegal index.");
 96         Node cur = dummyhead.next;
 97         for (int i = 0; i < index; i++) {
 98             cur = cur.next;
 99         }
100         cur.e = e;
101     }
102 
103     // 查找链表中是否有元素e
104     public boolean contains(E e) {
105         Node cur = dummyhead.next;
106         while(cur != null) {
107             if (cur.e.equals(e)) {
108                 return true;
109             }
110             cur = cur.next;
111         }
112         return false;
113     }
114     // 从列表中删除index位置处的元素,返回删除的元素
115     public E remove(int index) {
116         if (index < 0 || index >= size)
117             throw new IllegalArgumentException("Remove failed.Illegal index.");
118         Node prev = dummyhead;
119         for (int i = 0; i < index; i ++) {
120             prev = prev.next;
121         }
122         Node retNode = prev.next;
123         prev.next = retNode.next;
124         retNode.next = null;
125         size --;
126 
127         return retNode.e;
128     }
129     // 从链表中删除第一个元素,返回删除的元素
130     public E removeFirst() {
131         return remove(0);
132     }
133     // 从链表中删除最后一个元素
134     public E removeLast() {
135         return remove(size - 1);
136     }
137 
138     @Override
139     public String toString() {
140         StringBuilder res = new StringBuilder();
141 //        Node cur = dummyhead.next;
142 //        while(cur != null) {
143 //            res.append(cur + "->");
144 //            cur = cur.next;
145 //        }
146         for (Node cur = dummyhead.next; cur != null; cur = cur.next)
147             res.append(cur + "->");
148         res.append("NULL");
149         return res.toString();
150     }
151 }
LinkList
 1 /**
 2  * @author 阿遠
 3  * Date: 2019/1/17
 4  * Time: 11:15
 5  */
 6 public class LinkedListStack<E> implements Stack<E> {
 7 
 8     private LinkedList<E> list;
 9 
10     public LinkedListStack(){
11         list = new LinkedList<E>();
12     }
13 
14     @Override
15     public int getSize() {
16         return list.getSize();
17     }
18 
19     @Override
20     public boolean isEmpty() {
21         return list.isEmpty();
22     }
23 
24     @Override
25     public void push(E e) {
26         list.addFirst(e);
27     }
28 
29     @Override
30     public E pop() {
31         return list.removeFirst();
32     }
33 
34     @Override
35     public E peek() {
36         return list.getFirst();
37     }
38 
39     @Override
40     public String toString() {
41         StringBuilder res = new StringBuilder();
42         res.append("Stack: top ");
43         res.append(list);
44         return res.toString();
45     }
46 
47 }
LinkedListStack

 3.1测试

 1 public class Main {
 2 
 3     public static void main(String[] args) {
 4 
 5         LinkedListStack<Integer> stack = new LinkedListStack<Integer>();
 6 
 7         for (int i = 0; i < 5; i++) {
 8             stack.push(i);
 9         }
10         System.out.println(stack);
11         stack.pop();
12         System.out.println("出栈:");
13         System.out.println(stack);
14     }
15 }

 3.2测试结果

Stack: top 4->3->2->1->0->NULL
出栈:(后进先出)
Stack: top 3->2->1->0->NULL

4.应用实例

  该应用实例是解决LeetCode上面的一道题——有效的括号。点击前往

题目:

  给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

  有效字符串需满足:

            1.左括号必须用相同类型的右括号闭合。

            2.左括号必须以正确的顺序闭合。

  注意空字符串可被认为是有效字符串。

答案:

 1 /**
 2  * @author 阿遠
 3  * Date: 2019/1/14
 4  * Time: 16:19
 5  */
 6 
 7 import java.util.Stack;
 8 
 9 /**
10  * 有效的括号,这里使用的java.util包下的Stack类实现
11  */
12 public class SolutionOne {
13 
14     public boolean isValid(String s) {
15         Stack<Character> stack = new Stack<Character>();
16         for (int i = 0; i < s.length(); i++) {
17             char c = s.charAt(i);
18             // 如果括号为左括号则将其压入栈中
19             if (c == '(' || c == '[' || c == '{'){
20                 stack.push(c);
21             } else {
22                 // 如果栈为空说明不是以左括号开始,直接退出
23                 if (stack.isEmpty()) {
24                     return false;
25                 }
26                 // 取出栈顶元素匹配
27                 char topChar = stack.pop();
28                 if (c == ')' && topChar != '(')
29                     return false;
30                 if (c == ']' && topChar != '[')
31                     return false;
32                 if (c == '}' && topChar != '{')
33                     return false;
34             }
35         }
36         return stack.isEmpty();  // 只有当最后stack的字符串全部被匹配时才是成功的
37     }
38     public static void main(String[] args){
39          System.out.println((new SolutionOne()).isValid("(){}[]"));
40          System.out.println((new SolutionOne()).isValid("(}[]"));
41     }
42 }
原文地址:https://www.cnblogs.com/a-yuan/p/10270469.html