대기열의 기본 사항을 빠르게 익히세요

큐는 한쪽(큐의 꼬리)에서만 삽입 작업을 허용하고 다른 쪽(큐의 헤드)에서는 삭제 작업만 허용하는 선형 데이터 구조입니다. 삽입 작업을 대기열에 넣기(enqueuing)라고 하고 삭제 작업을 대기열에서 빼기(dequeuing)라고 합니다. 큐는 FIFO(선입선출) 원칙을 따릅니다. 즉, 큐의 선두에 있는 요소가 먼저 삭제되고 큐의 끝에 있는 요소가 마지막에 삭제됩니다.

여기에 이미지 설명을 삽입하세요.

대기열 특성

  1. 선입선출: 대기열에 있는 요소는 대기열에 들어간 순서대로 제거됩니다. 즉, 대기열에 먼저 들어간 요소가 먼저 제거됩니다.
  2. 제한된 용량: 대기열에는 일반적으로 특정 최대 용량이 있습니다. 대기열이 최대 용량에 도달하면 새 요소가 대기열에 들어갈 수 없습니다.
  3. 기본 연산: 큐는 삽입(enqueue)과 삭제(dequeue)라는 두 가지 기본 연산을 지원하며 삽입 연산은 큐의 꼬리에서 수행되고 삭제 연산은 큐의 선두에서 수행됩니다.

연결리스트 기반 큐 구현

이 구현 방법은 다음과 같이 비교적 간단합니다.

public class LinkQueue {
    
    
    // 头节点
    private  Node front;
    //尾节点
    private Node rear;
    //队列大小
    private int size;
    public LinkQueue(){
    
    
        //初始化头节点和尾节点
        this.front = new Node(0);
        this.rear = new Node(0);
    }
    /**
     *入队
     */
    public  void push(int value){
    
    
     //创建新节点
     Node newNode = new Node(value);
      //临时节点指向头节点
      Node temp = front;
      //循环遍历,直到临时节点指向尾节点
      while (temp.next!=null){
    
    
          temp = temp.next;
      }
      //将新节点指向头节点
      temp.next = newNode;
      //将尾节点指向新节点
      rear = newNode;
      //队列大小加1
      size++;
    }
    /**
     * 出队
     */
    public int pull(){
    
    
       //如果队列为空,则提示
       if(front.next==null){
    
    
           System.out.println("队列已经为空!");
       }
       //获取头节点指向的节点
       Node fristNode = front.next;
       //将头节点指向头节点指向的节点的下一个节点
       front.next = fristNode.next;
       //队列大小减1
       size--;
       //返回头节点指向的节点
       return fristNode.data;
    }
    /**
     * 遍历队列
     */
    public  void  traverse(){
    
    
       //临时节点指向头节点指向的节点
       Node temp = front.next;
       //循环遍历,直到临时节点指向尾节点
       while (temp!=null){
    
    
           //输出临时节点指向的节点
           System.out.printf(temp.data+"\t");
           //将临时节点指向临时节点指向的节点的下一个节点
           temp = temp.next;
       }
    }
   //测试方法
    public static void main(String[] args) {
    
    
     //创建一个队列
     LinkQueue linkQueue = new LinkQueue();
     //将1,2,3入队
     linkQueue.push(1);
     linkQueue.push(2);
     linkQueue.push(3);
        //输出第一个出队的元素
        System.out.println("第一个出队的元素为"+linkQueue.pull());
        //输出队列中的元素
        System.out.println("队列中的元素为");
        linkQueue.traverse();

    }

}
class Node{
    
    
    //节点数据
    public  int data;
    //指向下一个节点
    public Node next;
    //构造函数
    public Node(int data){
    
    
        this.data = data;
    }
}

먼저, 대기열의 노드를 나타내기 위해 Node 클래스가 정의됩니다. 각 노드에는 데이터 항목과 다음 노드에 대한 포인터가 포함되어 있습니다.
LinkQueue 클래스에는 세 가지 개인 속성이 정의됩니다. front는 대기열의 헤드 노드를 나타내고, Rear는 대기열의 tail 노드를 나타내며, size는 대기열의 크기를 나타냅니다.
생성자 LinkQueue()는 대기열을 초기화하는 데 사용되며, 헤드 노드와 테일 노드를 생성하고 해당 값을 ​​​​0으로 만듭니다.
push() 메소드는 큐에 요소를 추가하는 작업, 즉 큐에 요소를 추가하는 데 사용됩니다. 먼저 새 노드를 생성한 다음 꼬리 노드를 찾을 때까지 임시 노드를 통해 대기열을 순회하고 새 노드를 꼬리 노드에 연결한 다음 새 꼬리 노드를 가리키도록 후면 포인터를 업데이트합니다. 마지막으로 대기열 크기를 1씩 늘립니다.
pull() 메소드는 큐에서 요소를 제거하는 작업, 즉 큐에서 요소를 제거하는 데 사용됩니다. 먼저 대기열이 비어 있는지 확인하고, 비어 있으면 대기열이 비어 있다는 메시지가 표시됩니다. 그런 다음 대기열 헤드에서 노드를 제거하고 다음 노드를 가리키도록 앞쪽을 업데이트하고 대기열 크기를 1만큼 줄입니다. 마지막으로 제거된 노드의 값이 반환됩니다.
traverse() 메소드는 대기열을 순회하고 대기열의 모든 요소를 ​​인쇄하는 데 사용됩니다.

스택을 사용하여 큐 구현

스택을 구현하기 위해 대기열을 사용하는 것은 질문 232와 같은 많은 질문에서 접하게 됩니다.

MyQueue 클래스를 구현합니다.

  • void push(int x) 요소 x를 큐의 끝으로 푸시합니다.
  • int pop()은 대기열의 시작 부분에서 요소를 제거하고 반환합니다.
  • int peek()는 대기열의 시작 부분에 있는 요소를 반환합니다.
  • booleanempty()는 대기열이 비어 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

이 질문에 대한 우리의 구현 아이디어는 두 개의 스택(입력 스택 하나와 출력 스택 하나)을 사용하는 것입니다. 데이터 입력은 입력 스택으로 푸시됩니다. 데이터가 출력되면 출력 스택에서 팝됩니다. 출력 스택이 비어 있을 때 , 입력 스택의 모든 데이터를 팝하고 출력 스택으로 푸시해야 합니다. 구체적인 코드 예시는 다음과 같습니다.

class MyQueue {
    
    
  Deque<Integer> inStack = null;
  Deque<Integer> outStack = null;
    public MyQueue() {
    
    
     inStack = new LinkedList<>();
     outStack = new LinkedList<>();
    }
    
    public void push(int x) {
    
    
      inStack.push(x);
    }
    
    public int pop() {
    
    
     if(outStack.isEmpty()){
    
    
         in2out();
     }
     return outStack.pop();
    }
    
    public int peek() {
    
    
    if(outStack.isEmpty()){
    
    
        in2out();
    }
    return outStack.peek();
    }
    
    public boolean empty() {
    
    
    return inStack.isEmpty()&&outStack.isEmpty();
    }
    public void in2out(){
    
    
        while (!inStack.isEmpty()){
    
    
            outStack.push(inStack.pop());
        }
    }
}

큐를 사용하여 스택 구현

Likou 225 질문을 살펴보겠습니다.
후입선출(LIFO) 스택을 구현하려면 두 개의 대기열만 사용하고 일반 스택의 네 가지 작업을 모두 지원하세요. (푸시, 상단, 팝 및 비어 있음).

MyStack 클래스를 구현합니다.

  • void push(int x) 요소 x를 스택의 맨 위로 밀어 넣습니다.
  • int pop()은 스택의 최상위 요소를 제거하고 반환합니다.
  • int top()은 스택의 최상위 요소를 반환합니다.
  • booleanempty() 스택이 비어 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

이 질문에 대한 우리의 구현 아이디어는 두 개의 대기열을 사용하는 것입니다. 팝업 순서를 용이하게 하기 위해 새로 푸시된 요소를 대기열의 앞쪽에 배치해야 합니다. 순서는 마지막에서 먼저 나오므로 대기열 2를 사용하여 대기열을 지원합니다. 1을 작동시킵니다. 푸시 작업의 요소를 먼저 대기열 2에 넣은 다음 대기열 1의 모든 요소를 ​​대기열에서 빼고 대기열 2에 넣은 다음 대기열 1과 대기열 2를 서로 교환한 다음 요소를 대기열 1에는 스택 요소의 요소가 있습니다.

class MyStack {
    
    
   Queue<Integer> queue1 = null;
   Queue<Integer> queue2 = null;
    public MyStack() {
    
    
  queue1 = new LinkedList<>();
  queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
    
    
     //将元素x压入队列2
     queue2.offer(x);
     //将队列1中的元素压入队列2,并将其弹出
     while (!queue1.isEmpty()){
    
    
         queue2.offer(queue1.poll());
     }
     //交换队列1和队列2
     Queue<Integer> temp = queue1;
     queue1 = queue2;
     queue2 = temp;
    }
    
    public int pop() {
    
    
      //从队列1中弹出元素
      return   queue1.poll();
    }
    
    public int top() {
    
    
      //返回队列1的第一个元素
      return queue1.peek();
    }
    
    public boolean empty() {
    
    
   //判断队列1是否为空
   return queue1.isEmpty();
    }
}

큐는 중요한 데이터 구조로 "선입선출(first in, first out)"의 특성을 가지며 데이터를 순서대로 저장하고 액세스하는 데 자주 사용됩니다. 대기열의 기본 개념, 특성 및 일반적인 작동을 이해하는 것은 컴퓨터 과학 분야에서 학습하고 작업하는 데 매우 중요합니다. 실제 응용 프로그램에서 대기열은 네트워크 전송, 운영 체제, 작업 대기열 및 인쇄 대기열을 포함하여 광범위한 용도로 사용됩니다.

추천

출처blog.csdn.net/st200112266/article/details/134296427