2.1栈
栈(stack),也称堆栈,是一种操作受限的线性表,栈只允许在线性表的一端进行操作。
在线性表中进行操作的一端叫栈顶(top),栈顶保存的元素叫栈顶元素,相对一端叫栈底(bottom)。
栈的操作只允许在栈顶操作,元素先入后出。(First In Last Out简称FILO)
如果没有元素称为空栈。
向栈中插入元素叫进栈或入栈,删除元素叫退栈或出栈。
/** * @author Rose * @Email 510130303@qq.com * @date 2020/8/6 9:59 * 定义栈的操作 * */ public interface MyStack { int getSize(); //返回元素个数 boolean isEmpty(); //判断是否为空 void push(Object e); //压栈 Object pop(); //弹栈 Object peek(); //返回栈顶元素 }
2.1.1栈的顺序存储
//堆栈的顺序实现 public class MyArrayStack implements MyStack { private Object[] elements; //数组存储堆栈元素 private static final int DEFAULT_CAPACITY = 16; //数组默认大小 private int top; //栈顶指针 //默认构造 public MyArrayStack(){ elements = new Object[DEFAULT_CAPACITY]; } //有参构造,给数组赋予大小 public MyArrayStack(int initialCapacity){ elements = new Object[initialCapacity]; } //返回堆栈大小 @Override public int getSize() { return top; } //判断堆栈是否为空 @Override public boolean isEmpty() { return top <= 0; } //入栈 @Override public void push(Object e) { //判断堆栈是否已满 //已满,数组扩容 if (top >= elements.length){ //定义一个是原来2倍大的新数组 Object[] newElements = new Object[elements.length * 2]; //把旧数组内容复制到新数组 for (int i = 0;i < elements.length;i++){ newElements[i] = elements[i]; } //让原来的旧数组指向新数组 elements = newElements; } //把 e 存入栈顶位置 elements[top] = e; //栈顶指针修改指向 top++; } //出栈 @Override public Object pop() { //判断堆栈是否为空 if (top <= 0){ throw new StackOverflowError("栈已空"); } top--; return elements[top]; } //返回栈顶元素 @Override public Object peek() { //判断堆栈是否为空 if (top <= 0){ throw new StackOverflowError("栈已空"); } return elements[top-1]; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); //从栈顶到栈底顺序遍历 for (int i = top-1;i >= 0;i--){ sb.append(elements[i]); if (i > 0){ sb.append(","); } } sb.append("]"); return sb.toString(); } }
public class MyArrayStackTest { public static void main(String[] args) { MyArrayStack myArrayStack = new MyArrayStack(); //返回堆栈大小 System.out.println(myArrayStack.getSize()); //判断堆栈是否为空 System.out.println(myArrayStack.isEmpty()); //入栈 myArrayStack.push("飞"); myArrayStack.push("云"); myArrayStack.push("沈"); System.out.println(myArrayStack.getSize()); System.out.println(myArrayStack.isEmpty()); System.out.println(myArrayStack); //弹栈 Object pop = myArrayStack.pop(); System.out.println(pop); System.out.println(myArrayStack); //返回栈顶元素 Object peek = myArrayStack.peek(); System.out.println(peek); } }
2.1.2栈的链式存储
也称链栈
栈只允许在线性表的一端操作,可以选择链表的首结点作为栈顶,操作都在首结点上进行。
//栈的链式存储 public class MyLinkedStack implements MyStack { private Node top; //存储栈顶指针的引用 private int size; //存储堆栈中的元素个数 //内部类,描述链表的结点 private class Node{ Object data; //存储数据 Node next; //存储下一个结点引用 public Node(Object data, Node next) { this.data = data; this.next = next; } } //返回堆栈大小 @Override public int getSize() { return size; } //判断堆栈是否为空 @Override public boolean isEmpty() { return size == 0; } //入栈 @Override public void push(Object e) { //创建新结点,插入到链表头部 Node pNode = new Node(e,top); //修改top指针指向新结点 top = pNode; size++; } //出栈 @Override public Object pop() { //判断堆栈是否为空 if (size < 1){ throw new StackOverflowError("栈已空"); } Object old = top.data; //旧数据 top = top.next; //栈顶指针后移 size--; return old; } //返回栈顶元素 @Override public Object peek() { //判断堆栈是否为空 if (size < 1){ throw new StackOverflowError("栈已空"); } return top.data; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (Node pNode = top;pNode != null;pNode = pNode.next){ sb.append(pNode.data); if (pNode.next != null){ sb.append(","); } } sb.append("]"); return sb.toString(); } }
public class MyLinkedStackTest { public static void main(String[] args) { MyLinkedStack myLinkedStack = new MyLinkedStack(); //插入 myLinkedStack.push("飞"); myLinkedStack.push("云"); myLinkedStack.push("沈"); //大小 System.out.println(myLinkedStack.getSize()); //为空 System.out.println(myLinkedStack.isEmpty()); System.out.println(myLinkedStack); //栈顶元素 System.out.println(myLinkedStack.peek()); } }
2.1.3栈的应用
一 将十进制整数转换成任意进制数
/** * @author Rose * @Email 510130303@qq.com * @date 2020/8/7 8:55 * 将十进制整数num转换成decimal指定进制数 * */ public class MyArrayStackUtils { public static void main(String[] args) { System.out.println(convert(100,2)); System.out.println(convert(100,8)); System.out.println(convert(100,16)); } public static String convert(int num,int decimal){ MyArrayStack myArrayStack = new MyArrayStack(); //保存余数 int remainder = num % decimal; //计算余数 while (num != 0){ myArrayStack.push(remainder); //余数压栈 num = num / decimal; remainder = num % decimal; } StringBuilder sb = new StringBuilder(); while (!myArrayStack.isEmpty()){ sb.append(myArrayStack.pop()); //弹栈 } return sb.toString(); } }
二 匹配括弧
/** * @author Rose * @Email 510130303@qq.com * @date 2020/8/7 9:16 * 括弧匹配 * */ public class BracketMatch { public static void main(String[] args) { System.out.println(bracketMatch("[{()}]")); System.out.println(bracketMatch("{{))")); } //检测表达式expression中的括弧是否合法 public static boolean bracketMatch(String expression){ MyArrayStack myArrayStack = new MyArrayStack(); //保存左括弧 //遍历整个表达式,如果是左括弧就入栈,如果是右括弧,就出栈 for (int i = 0;i < expression.length();i++){ //取出每个字符 char c = expression.charAt(i); switch (c) { case '(': case '[': case '{': myArrayStack.push(c); break; case ')': //如果栈不为空,且弹栈的元素和左括弧一样,则成功 if (!myArrayStack.isEmpty() && myArrayStack.pop().equals('(')){ break; }else return false; case ']': if (!myArrayStack.isEmpty() && myArrayStack.pop().equals('[')){ break; }else return false; case '}': if (!myArrayStack.isEmpty() && myArrayStack.pop().equals('{')){ break; }else return false; } } if (myArrayStack.isEmpty()){ return true; }else return false; } }
3.1队列
3.1.1队列的顺序存储
/** * @author Rose * @Email 510130303@qq.com * @date 2020/8/7 10:54 * 队列的顺序存储 * */ public class MyArrayQueue { private Object[] elements; //存储队列元素 private static final int DEFAULT_CAPACITY = 8; //数组默认大小 private int front; //队首 private int rear; //队尾 private int size; //元素个数 //有参构造 public MyArrayQueue() { elements = new Object[DEFAULT_CAPACITY]; } //无参构造 public MyArrayQueue(int initialCapacity) { elements = new Object[initialCapacity]; } //返回元素个数 public int getSize(){ return size; } //判断是否为空 public boolean isEmpty(){ return size == 0; } //入队 public void enQueue(Object e){ //如果数组已满,扩容 if (size >= elements.length){ expandQueue(); } elements[rear] = e; //元素存储到rear所指位置 rear = (rear + 1) % elements.length; //指针后移 size++; } //出队 public Object deQueue(){ //队列为空,异常 if (size <= 0){ throw new QueueRuntimeException("队列为空"); } //队列不为空,返回front所指元素 Object old = elements[front]; //后移 front = (front + 1) % elements.length; size--; return old; } //返回首元素 public Object peek(){ //队列为空 if (size <= 0){ throw new QueueRuntimeException("队列为空"); } return elements[front]; } //数组扩容 private void expandQueue() { //创建一个长度是原来2倍的新数组 Object[] newElements = new Object[elements.length * 2]; //将旧数组复制到新数组中去 for (int i = 0;i < size;i++){ newElements[i] = elements[front]; front = (front + 1) % elements.length; //后移 } //修改旧数组指向新数组 elements = newElements; //调整队首队尾指针 front = 0; rear = size; } public String toString(){ if (size <= 0){ return null; } StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0;i < size;i++){ sb.append(elements[front]); front = (front + 1) % elements.length; if (rear != front){ sb.append(","); } } sb.append("]"); return sb.toString(); } //异常内部类 class QueueRuntimeException extends RuntimeException { public QueueRuntimeException() { super(); } public QueueRuntimeException(String message) { super(message); } } }
public class MyArrayQueueTest { public static void main(String[] args) { MyArrayQueue myArrayQueue = new MyArrayQueue(3); System.out.println(myArrayQueue.getSize()); System.out.println(myArrayQueue.isEmpty()); myArrayQueue.enQueue("沈"); myArrayQueue.enQueue("云"); myArrayQueue.enQueue("飞"); System.out.println(myArrayQueue); System.out.println(myArrayQueue.peek()); myArrayQueue.deQueue(); myArrayQueue.deQueue(); System.out.println(myArrayQueue); myArrayQueue.deQueue(); System.out.println(myArrayQueue); // myArrayQueue.deQueue(); } }
3.1.2队列的链式存储
/** * @author Rose * @Email 510130303@qq.com * @date 2020/8/7 16:23 * 队列的连式存储 * */ public class MyLinkedQueue { private Node front; //队首 private Node rear; //队尾 private int size; //元素个数 //内部类 private class Node{ Object element; Node next; public Node(Object element, Node next) { this.element = element; this.next = next; } } //返回元素个数 public int getSize(){ return size; } //判断队列是否为空 public boolean isEmpty(){ return size == 0; } //入队 public void enQueue(Object e){ //生成一个结点 Node newNode = new Node(e, null); //把结点添加到队列中 //如果 rear 为null,那么这是一个空队列 if (rear == null){ front = newNode; rear = newNode; }else { //如果 raer 不为空,那么添加新结点到 队尾rear的下一个结点 rear.next = newNode; //修改队尾指向 rear = newNode; } //元素个数增加 size++; } //出队 public Object deQueue(){ //判断队列是否为空 if (size <= 0){ throw new QueueRuntimeException("队列为空"); } //存储旧数据 Object old = front.element; //指针后移 front = front.next; //出队之后,队空了,调整队尾指针 if (front == null){ rear = null; } //元素数量降低 size--; return old; } //返回队首元素 public Object peek(){ return front.element; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); //队尾空,返回null if (size <= 0){ return null; } for (Node pNode = front;pNode != null;pNode = pNode.next){ sb.append(pNode.element); if (pNode.next != null){ sb.append(","); } } sb.append("]"); return sb.toString(); } //异常内部类 class QueueRuntimeException extends RuntimeException { public QueueRuntimeException() { super(); } public QueueRuntimeException(String message) { super(message); } } }
public class MyLinkedQueueTest { public static void main(String[] args) { MyLinkedQueue myLinkedQueue = new MyLinkedQueue(); System.out.println(myLinkedQueue.getSize()); System.out.println(myLinkedQueue.isEmpty()); myLinkedQueue.enQueue("沈"); myLinkedQueue.enQueue("云"); myLinkedQueue.enQueue("飞"); System.out.println(myLinkedQueue); System.out.println(myLinkedQueue.getSize()); System.out.println(myLinkedQueue.isEmpty()); System.out.println(myLinkedQueue.peek()); } }