学习数据结构Day3

栈和队列

 

  • 栈是一种线性结构,相比数组
  • 他对应的操作是数组的子集
  • 只能从一端进入,也只能从一端取出
  • 这一端成为栈顶

栈是一种先进后出的数据结构,Last In First Out(LIFO)

  • 程序调用的系统栈
  • 栈的应用:无处不在的Undo操作(撤销)

 

栈的实现

Stack

  • void push(E)
  • E pop()
  • E peek()
  • int getSize()
  • boolean isEmpty()

 

将自己写的栈设置为接口,然后用第一天的动态数组实现这个接口。因为有了上一个自己做的动态数组,所以栈的形

 

成是非常方便的。

 

public class ArrayStack<E> implements Stack<E> {   DynamicArray<E> array;   public ArrayStack(int capacity){  array = new DynamicArray<E>(capacity);  }   public ArrayStack(){  array = new DynamicArray<E>();  }   @Override  public int getSize() {  return array.getSize();  }   @Override  public void push(E e) {  array.addLast(e);  }   @Override  public boolean isEmpty() {  return array.isEmpty();  }   @Override  public E pop() {  return array.removeLast();  }   @Override  public E peek() {  return array.getLast();  }   public int getCapacity(){  return array.capacity();  }   @Override  public String toString(){  StringBuilder builder = new StringBuilder();  builder.append("stack:");  builder.append("[");  for (int i = 0; i < array.getSize(); i++) {  builder.append(array.get(i));  if(i != array.getSize()-1){  builder.append(", ");  }  }  builder.append("] top");  return builder.toString();  } 

 

时间复杂度都是O(1),其中,push和pop都是均摊为O(1)

 

队列

 

队列也是一个线性结构,有队首和队尾。先进先出。我们自己去编写一个队列。要实现以下方法

  • void enqueue(E)
  • E dequeue()
  • E getFront()
  • int getSize()
  • boolean isEmpty()

 


public interface Queue<E> {  int getSize();  boolean isEmpty();  void enqueue(E e);  E dequeue();  E getFront(); }  public class ArrayQueue<E> implements Queue<E>{   private DynamicArray array;   public ArrayQueue(int capacity) {  array = new DynamicArray<>(capacity);  }   public ArrayQueue() {  array = new DynamicArray();  }   @Override  public int getSize() {  return array.getSize();  }   @Override  public boolean isEmpty() {  return array.isEmpty();  }   @Override  public void enqueue(E e) {  array.addLast(e);  }   public int getCapacity(){  return array.capacity();  }   @Override  public E dequeue() {  return (E) array.removeFirst();  }   @Override  public E getFront() {  return null;  }   @Override  public String toString(){  StringBuilder builder = new StringBuilder();  builder.append("Queue:");  builder.append("front [");  for (int i = 0; i < array.getSize(); i++) {  builder.append(array.get(i));  if(i != array.getSize()-1){  builder.append(", ");  }  }  builder.append("]");  return builder.toString();  } } 

 

写完这个队列我们发现,这个队列,出队列的时间复杂度是O(n),严重的影响了运算效率,所以我们利用指针,指出

 

首尾指针,所以维护指针就可以了。所以,基于这样的想法,我们就想出了循环队列的队列。

 

front == tail 队列为空

( tail +1 )% c== front 队列满

在capacity中,浪费了一个空间。

 

package Queue;
   /**  * @author shkstart  * @create 2019-11-25 20:05  */ public class LoopQueue<E> implements Queue<E> {   private E[] data;   private int front, tail;   private int size;   public LoopQueue(int capacity) {  data = (E[]) new Object[capacity + 1];  front = 0;  tail = 0;  size = 0;  }   public LoopQueue() {  this(10);  }   public int getCapacity() {  return data.length - 1;  }   @Override  public int getSize() {  return size;  }   /**  * 判断是否为空的条件  *  * @return  */  @Override  public boolean isEmpty() {  return tail == front;  }   /**  * 如队列的操作!一定不要忘了循环队列维护  *  * @param e  */  @Override  public void enqueue(E e) {  if ((tail + 1) % data.length == front) {//队列满  resize(getCapacity() * 2);  }   data[tail] = e;  tail = (tail + 1) % data.length;  size++;  }   private void resize(int newCapacity) {  E[] newdata = (E[]) new Object[newCapacity];  for (int i = 0; i < size; i++) {  newdata[i] = data[(front + i) % data.length];   data = newdata;  front = 0;  tail = size;  }  }   @Override  public E dequeue() {   if (isEmpty()) {  throw new IllegalArgumentException("Cannot dequeue from an empty queue");  }  E ret = data[front];  data[front] = null;  front = (front + 1) % data.length;  size--;  if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {  resize(getCapacity() / 2);  }  return ret;  }   @Override  public E getFront() {  if (isEmpty()) {  throw new IllegalArgumentException("Cannot dequeue from an empty queue");  }  return data[front];  } @Override public String toString() { StringBuilder res = new StringBuilder(); res.append(String.format("Queue: size = %d , capacity = %d\n", size, getCapacity())); res.append("front ["); for(int i = front ; i != tail ; i = (i + 1) % data.length){ res.append(data[i]); if((i + 1) % data.length != tail) res.append(", ");  } res.append("] tail"); return res.toString();  } public static void main(String[] args) { LoopQueue<Integer> arrayQueue = new LoopQueue<Integer>(); for (int i = 0; i < 10; i++) { arrayQueue.enqueue(i); System.out.println(arrayQueue); if(i % 3 == 2){ arrayQueue.dequeue(); System.out.println(arrayQueue);  }  }  } } 

 

你可能感兴趣的:(学习数据结构Day3)