Algorithm and data structure 04 queue

Posted by ahzulfi on Fri, 14 Jan 2022 17:35:23 +0100

  1. queue
  • Queue is another special linear table. Its particularity is that queue only allows inserting data elements at the end of the table and deleting data elements at the header. It has the characteristics of first in, first out, then in and then out.
  • We call the end that is allowed to be deleted as the front and the end that is inserted as the rear
    A queue without any data elements is called an empty queue.
  • Queue insertion is called queue joining; The deletion of a queue is called a queue.
  • The queue is also a finite sequence composed of n (n > = 0) data elements with the same type. Several operations are similar to stack:
    (1) clear queue (): empty an existing queue
    (2) Empty judgment isEmpty(): judge whether a sequence is empty. If it is empty, it returns true; If it is not empty, false is returned;
    (3) Find queue length (): returns the number of data elements in the queue
    (4) Take the first element peek (): read the first element and return the value
    (5) Queue operation offer (): insert a new data element into the queue and make it a new tail element
    (6) Out of queue operation poll(): delete the queue head element and return its value. If the queue is empty, return null;
    Describe with Java interface:
public interface Queue<E> extends Iterable<E> {
  public void offer(E element);   //Join the team
  public E poll();    //Out of the team
  public E peek();    //View team leader element
  public boolean isEmpty();
  public void clear();
  public int size();
}
  • Queues also have sequential and chained storage structures. The queue of sequential storage structure is called sequential queue, and the queue of chain storage structure is called chain queue.
    Code implementation:
public class ArrayQueue <E> implements Queue<E> {
  private ArrayList<E> list;
  public ArrayQueue() {
    list = new ArrayList<>();
  }

  @Override
  public void offer(E element) {
    list.add(list.size(), element);
  }

  @Override
  public E poll() {
    return list.remove(0);
  }

  @Override
  public E peek() {
    return list.get(0);
  }

  @Override
  public boolean isEmpty() {
    return list.isEmpty();
  }

  @Override
  public void clear() {
    list.clear();
  }

  @Override
  public int size() {
    return list.size();
  }

  @Override
  public Iterator<E> iterator() {
    return list.iterator();
  }

  @Override
  public String toString() {
    return list.toString();
  }

  @Override
  public boolean equals(Object o) {
    if (o == null) {
      return false;
    }
    if (this == o) {
      return true;
    }
    if (o instanceof ArrayQueue) {
      ArrayQueue other = (ArrayQueue) o;
      return list.equals(other.list);
    }
    return false;
 }
  1. Implement queue with stack

Create two stacks, one for data (data stack) and one for auxiliary (auxiliary stack). When adding data, the stack will be pressed in turn. When fetching data, the top element of the stack will be fetched. However, we want to simulate the first in first out of the queue, so we have to fetch the bottom element of the stack. Then the auxiliary stack will come in handy. Pop up the elements of the data stack to the auxiliary stack in turn, but keep the last element. Finally, there is the last element left in the data stack. Return the element directly, At this time, the data stack has no data. Finally, press the elements of the auxiliary stack into the data stack in turn. In this way, we successfully get the elements at the bottom of the stack.
Code implementation:

public static void main(String[] args) {
    QueueImplByStack<Integer> queue = new QueueImplByStack<>();
    for (int i = 1; i <= 5; i++) {
      queue.offer(i);
    }
    System.out.println(queue);
    System.out.println(queue.poll());
    System.out.println(queue);
  }
}
class QueueImplByStack<E> implements Queue<E> {
  private ArrayStack<E> stackA;
  private ArrayStack<E> stackB;
  public QueueImplByStack() {
    stackA = new ArrayStack<>();
    stackB = new ArrayStack<>();
  }

  @Override
  public void offer(E element) {
    stackA.push(element);
  }

  @Override
  public E poll() {
    if (isEmpty()) {
      throw new IllegalArgumentException("queue is null");
    }
    while (stackA.size() != 1) {
      stackB.push(stackA.pop());
    }
    E ret = stackA.pop();

    while (!stackB.isEmpty()) {
      stackA.push(stackB.pop());
    }
    return ret;
  }

  @Override
  public E peek() {
    if (isEmpty()) {
      throw new IllegalArgumentException("queue is null");
    }
    while (stackA.size() != 1) {
      stackB.push(stackA.pop());
    }
    E ret = stackA.peek();

    while (!stackB.isEmpty()) {
      stackA.push(stackB.pop());
    }
    return ret;
  }

  @Override
  public boolean isEmpty() {
    return stackA.isEmpty();
  }

  @Override
  public void clear() {
    stackA.clear();
  }

  @Override
  public int size() {
    return stackA.size();
  }

  @Override
  public Iterator<E> iterator() {
    return stackA.iterator();
  }

  @Override
  public String toString() {
    return stackA.toString();
  }
}
  1. Queue implementation stack

The idea is similar to the above: there are data queue and auxiliary queue. The first in and last out of the simulation stack. The queue is the last in and the first out of the queue, that is, each value should take the last element of the queue. The data queue goes out of the queue to the auxiliary queue, leaving the last element to return, and then the auxiliary queue goes out of the queue to the data queue

Code implementation:

public class QueueToStack {
  public static void main(String[] args) {
    StackImplByQueue<Integer> stack = new StackImplByQueue<>();
    System .out.println(stack);
    for (int i = 1; i <= 5; i++) {
      stack.push(i); //Queue A
    }
    System .out.println(stack.toString());
    System .out.println(stack.pop());
    System .out.println(stack);  //Queue B

  }
}
class StackImplByQueue<E> implements Stack<E> {
  private ArrayQueue<E> queueA;
  private ArrayQueue<E> queueB;

  public StackImplByQueue() {
    queueA = new ArrayQueue<>();
    queueB = new ArrayQueue<>();
  }

  @Override
  public int size() {
    if (queueA.isEmpty() && queueB.isEmpty()) {
      return 0;
    } else if (!queueA.isEmpty()) {
      return queueA.size();
    } else {
      return queueB.size();
    }
  }

  @Override
  public boolean isEmpty() {
    return queueA.isEmpty() && queueB.isEmpty();
  }

  @Override
  public void push(E element) {
    if (queueA.isEmpty() && queueB.isEmpty()) {
      queueA.offer(element);
    } else if (!queueA.isEmpty()) {
      queueA.offer(element);
    } else {
      queueB.offer(element);
    }
  }

  @Override
  public E pop() {
    if (isEmpty()) {
      return null;
    }
    E ret = null;
    if (!queueA.isEmpty()) {
      while (queueA.size() != 1) {
        queueB.offer(queueA.poll());
      }
      ret = queueA.poll();
    } else {
      while (queueB.size() != 1) {
        queueA.offer(queueB.poll());
      }
      ret = queueB.poll();
    }
    return ret;
  }

  @Override
  public E peek() {
    if (isEmpty()) {
      return null;
    }
    E ret = null;
    if (!queueA.isEmpty()) {
      while (queueA.size() != 1) {
        queueB.offer(queueA.poll());
      }
      ret = queueA.poll();
      queueB.offer(ret);
    } else {
      while (queueB.size() != 1) {
        queueA.offer(queueB.poll());
      }
      ret = queueB.poll();
      queueA.offer(ret);
    }
    return ret;
  }

  @Override
  public void clear() {
    queueA.clear();
    queueB.clear();
  }

  @Override
  public Iterator<E> iterator() {
    if (isEmpty()) {
      return queueA.iterator();
    } else if (!queueA.isEmpty()) {
      return queueA.iterator();
    } else {
      return queueB.iterator();
    }
  }
  @Override
  public String toString() {
    if (isEmpty()) {
      return "[]";
    } else if (!queueA.isEmpty()) {
      return queueA.toString();
    } else {
      return queueB.toString();
    }
  }
  1. Traversal of application folder of queue

1. In the initial state, first put the first level directory folder A into the queue

2. Then start to judge whether the queue is empty

3. If the queue is not empty, exit the queue

4. Expand and traverse the outgoing folder

5. If the file is traversed, the file name will be printed directly

6. If you traverse to a folder, enter the pair

7. Then judge whether the queue is empty. If not, go out of the queue, expand the folder and traverse.

8. Wait until the queue is empty

public class DirectoryTraversal {
  public static void main(String[] args) {
    /*
     * A directory object is dequeued as long as the queue is not empty
     * Expand the directory object and start traversal. If a file is encountered, print the name. If another directory is encountered, enter the queue
     * */
    File dir = new File("Folder address");
    QueueImplByStack<File> queue = new QueueImplByStack<>();
    queue.offer(dir);
    while (!queue.isEmpty()) {
      File file = queue.poll();
      System.out.println("[" + file.getName() + "]");
      File[] files = file.listFiles();
      for (File f : files) {
        if (f.isFile()) {
          System.out.println(f.getName());
        } else {
          queue.offer(f);
        }
      }
    }
  }
}

Topics: Algorithm data structure queue