대열 의 실현 원리 와 분석

대열
github 주소
대열 은 일종 의 선형 구조 이다
배열 에 비해 대기 열 에 대응 하 는 동작 은 배열 의 부분 집합 입 니 다.
한 끝 (팀 끝) 에서 만 요 소 를 추가 할 수 있 고 다른 한 끝 (팀 첫 번 째) 에서 만 요 소 를 추출 할 수 있 습 니 다.
대기 열 은 먼저 나 온 데이터 구조 로 First In First Out (FIFO)
활용 단어 참조
운영 체제 에서 임 무 를 수행 하 는 줄 서기 등;
시간 복잡 도 분석
Array Queue 배열 대기 열
  • void enqueue (E) 팀 끝 에 요소 O (1) 를 추가 하여 평균 노점
  • E dequeue () 팀 의 첫 번 째 원소 O (n)
  • 추출
  • E getFront () 팀 의 첫 번 째 요소 O 획득 (1)
  • int getSize () 배열 대기 열 요소 수량 O (1)
  • boolean isEmpty () 는 공 O 여 부 를 판단 한다 (1)
  • 루프 큐 순환 대기 열
  • void enqueue (E) 팀 끝 에 요소 O (1) 를 추가 하여 평균 노점
  • E dequeue () 추출 팀 의 첫 번 째 요소 O (1) 평균 노점
  • E getFront () 팀 의 첫 번 째 요소 O 획득 (1)
  • int getSize () 배열 대기 열 요소 수량 O (1)
  • boolean isEmpty () 는 공 O 여 부 를 판단 한다 (1)
  • 의 원리
    배열 대기 열 VS 순환 대기 열
    배열 대기 열:
  • 입대 조작, 배열 꼬리 에 요 소 를 계속 추가
  • 팀 에서 작업 을 하고 배열 array [0] 위치 요 소 를 꺼 내 나머지 요 소 를 모두 앞으로 이동 합 니 다.array[i] = array[i+1];

  • 순환 대기 열:
  • 저장 요소 배열 은 data 이 고 배열 의 길 이 는 data. length 이 며 대기 열 용량 capacity = data. length - 1 이 며 대기 열 에 있 는 요소 의 수량 size 입 니 다.
  • 두 변 수 를 사용 하여 front, tail 은 각각 배열 의 선두 와 팀 의 꼬리 위 치 를 가리킨다.
  • front = = tail 시 대기 열 이 비어 있 습 니 다.배열 초기 설정 front = tail = 0 위치;
  • (tail + 1)% data. length = = front 일 때 대기 열 이 가득 합 니 다.
  • 입대 작업 을 하고 대기 열 이 가득 찼 는 지 확인 하 며 배열 을 원래 의 2 자리 로 확대 한다.resize(2*capacity);요 소 를 tail 이 가리 키 는 위치 에 놓 습 니 다. tail = (tail + 1)% data. length;
  • 팀 에서 작업 을 하고 front 가 가리 키 는 요 소 를 배열 에서 꺼 냅 니 다. front = (front + 1)% data. length;배열 의 요소 수량 이 배열 용량 의 1 / 4 이 고 배열 용량 의 2 부 등 0 을 제외 하고 배열 을 축소 하 는 지 확인 합 니 다.if(size == capacity/4 && capacity/2 != 0) resize(capacity/2);
  • resize 배열 확장 작업 은 원래 배열 의 요 소 를 front 에서 시작 합 니 다. i = 0, (front + i)% data. length 위치 요 소 를 취하 고 i 는 1 을 추가 합 니 다. size 요 소 를 꺼 낼 때 까지 오래된 배열 의 요 소 를 모두 새 배열 에 넣 습 니 다.for(int i = 0; i < size; i++)newData[i] = data[(i + front) % data.length];

  • 고정 배열 순환 대기 열 구현 방식 2:
  • 저장 요소 배열 은 data 이 고 배열 의 길 이 는 data. length
  • 입 니 다.
  • 3 개의 변수 front 를 사용 하여 팀 의 위 치 를 가리 키 는 요 소 를 가리 키 고 tail - 추가 할 위 치 를 가리킨다.size - 배열 에 저 장 된 요소 의 수량;
  • size = 0 일 때 대기 열 이 비어 있 습 니 다.size = = data. length, 대기 열 이 가득 찼 을 때;
  • 초기: front = tail = 0;size= 0; 대기 열 이 비어 있 음;
  • size < data. length, 입단 이 필요 할 때 요 소 를 tail 위치 에 놓 고 tail 이 배열 의 마지막 위치 에 왔 을 때 tail 은 0 위치 로 초기 화 합 니 다.tail = tail == data.length-1 ? 0 : tail + 1;
  • 만약 사이즈! =0. 팀 을 나 가 야 할 때 front 위치의 요 소 를 팀 에서 나 오고 front 가 배열 의 마지막 위치 에 왔 을 때 front 는 0 위치 로 초기 화 합 니 다.front = front == data.length-1 ? 0 : front + 1;

  • 이루어지다
    Queue
  • void enqueue (E) 팀 꼬리 에 원 소 를 추가
  • E dequeue () 팀 의 첫 번 째 요소 추출
  • E getFront () 팀 의 첫 번 째 요소 획득
  • int getSize () 배열 대기 열 요소 수량
  • boolean isEmpty () 가 비어 있 는 지 판단
  • 배열 대기 열
    public class ArrayQueue implements Queue {
    
        private Array array;
    
        public ArrayQueue(int capacity){
            array = new Array<>(capacity);
        }
    
        public ArrayQueue(){
            array = new Array<>();
        }
    
        @Override
        public int getSize(){
            return array.getSize();
        }
    
        @Override
        public boolean isEmpty(){
            return array.isEmpty();
        }
    
        public int getCapacity(){
            return array.getCapacity();
        }
    
        @Override
        public void enqueue(E e){
            array.addLast(e);
        }
    
        @Override
        public E dequeue(){
            return array.removeFirst();
        }
    
        @Override
        public E getFront(){
            return array.getFirst();
        }
    
        @Override
        public String toString(){
    
            StringBuilder res = new StringBuilder();
            res.append("Queue: ");
            res.append("front [");
            for(int i = 0 ; i < array.getSize() ; i ++){
                res.append(array.get(i));
                if(i != array.getSize() - 1)
                    res.append(", ");
            }
            res.append("] tail");
            return res.toString();
        }
    
        public static void main(String[] args){
    
            ArrayQueue queue = new ArrayQueue<>();
            for(int i = 0 ; i < 10 ; i ++){
                queue.enqueue(i);
                System.out.println(queue);
    
                if(i % 3 == 2){
                    queue.dequeue();
                    System.out.println(queue);
                }
            }
        }
    }
    

    순환 대기 열
    public class LoopQueue<E> implements Queue<E> {
    
        private E[] data;
        private int front, tail;
        private int size;  //       ,       ,      :
                           // LoopQueue    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 boolean isEmpty(){
            return front == tail;
        }
    
        @Override
        public int getSize(){
            return size;
        }
    
        @Override
        public void enqueue(E e){
    
            if((tail + 1) % data.length == front)
                resize(getCapacity() * 2);
    
            data[tail] = e;
            tail = (tail + 1) % data.length;
            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("Queue is empty.");
            return data[front];
        }
    
        private void resize(int newCapacity){
    
            E[] newData = (E[])new Object[newCapacity + 1];
            for(int i = 0 ; i < size ; i ++)
                newData[i] = data[(i + front) % data.length];
    
            data = newData;
            front = 0;
            tail = size;
        }
    
        @Override
        public String toString(){
    
            StringBuilder res = new StringBuilder();
            res.append(String.format("Queue: size = %d , capacity = %d
    "
    , 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> queue = new LoopQueue<>(); for(int i = 0 ; i < 10 ; i ++){ queue.enqueue(i); System.out.println(queue); if(i % 3 == 2){ queue.dequeue(); System.out.println(queue); } } } }

    배열 대기 열 VS 순환 대기 열
    import java.util.Random;
    
    public class Main {
    
        //     q  opCount enqueueu dequeue        ,  : 
        private static double testQueue(Queue<Integer> q, int opCount){
    
            long startTime = System.nanoTime();
    
            Random random = new Random();
            for(int i = 0 ; i < opCount ; i ++)
                q.enqueue(random.nextInt(Integer.MAX_VALUE));
            for(int i = 0 ; i < opCount ; i ++)
                q.dequeue();
    
            long endTime = System.nanoTime();
    
            return (endTime - startTime) / 1000000000.0;
        }
    
        public static void main(String[] args) {
    
            int opCount = 100000;
    
            ArrayQueue<Integer> arrayQueue = new ArrayQueue<>();
            double time1 = testQueue(arrayQueue, opCount);
            System.out.println("ArrayQueue, time: " + time1 + " s");
    
            LoopQueue<Integer> loopQueue = new LoopQueue<>();
            double time2 = testQueue(loopQueue, opCount);
            System.out.println("LoopQueue, time: " + time2 + " s");
        }
    }
    

    Leetcode 102. Binary Tree Level Order Traversal
    import java.util.ArrayList;
    import java.util.List;
    import javafx.util.Pair;
    
    /// Leetcode 102. Binary Tree Level Order Traversal
    /// https://leetcode.com/problems/binary-tree-level-order-traversal/description/
    ///         
    ///
    ///                          。
    ///          Leetcode         LoopQueue。
    ///           ,         。
    ///   ,              。
    ///     ,                     :)
    
    class Solution {
    
        /// Definition for a binary tree node.
        private class TreeNode {
            int val;
            TreeNode left;
            TreeNode right;
            TreeNode(int x) { val = x; }
        }
    
        private interface Queue<E> {
    
            int getSize();
            boolean isEmpty();
            void enqueue(E e);
            E dequeue();
            E getFront();
        }
    
        private class LoopQueue<E> implements Queue<E> {
    
            private E[] data;
            private int front, tail;
            private int size;  //       ,       ,      :
            // LoopQueue    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 boolean isEmpty(){
                return front == tail;
            }
    
            @Override
            public int getSize(){
                return size;
            }
    
            @Override
            public void enqueue(E e){
    
                if((tail + 1) % data.length == front)
                    resize(getCapacity() * 2);
    
                data[tail] = e;
                tail = (tail + 1) % data.length;
                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("Queue is empty.");
                return data[front];
            }
    
            private void resize(int newCapacity){
    
                E[] newData = (E[])new Object[newCapacity + 1];
                for(int i = 0 ; i < size ; i ++)
                    newData[i] = data[(i + front) % data.length];
    
                data = newData;
                front = 0;
                tail = size;
            }
    
            @Override
            public String toString(){
    
                StringBuilder res = new StringBuilder();
                res.append(String.format("Queue: size = %d , capacity = %d
    "
    , 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 List<List<Integer>> levelOrder(TreeNode root) { ArrayList<List<Integer>> res = new ArrayList<List<Integer>>(); if(root == null) return res; // LinkedList LoopQueue<Pair<TreeNode, Integer>> queue = new LoopQueue<Pair<TreeNode, Integer>>(); queue.enqueue(new Pair<TreeNode, Integer>(root, 0)); while(!queue.isEmpty()){ Pair<TreeNode, Integer> front = queue.dequeue(); TreeNode node = front.getKey(); int level = front.getValue(); if(level == res.size()) res.add(new ArrayList<Integer>()); assert level < res.size(); res.get(level).add(node.val); if(node.left != null) queue.enqueue(new Pair<TreeNode, Integer>(node.left, level + 1)); if(node.right != null) queue.enqueue(new Pair<TreeNode, Integer>(node.right, level + 1)); } return res; } }

    레 퍼 런 스
  • 유 우 파 의 과정, 정리 와 실천 을 배운다.
  • 좌 정 운 의 과정 을 배우 고 정리 와 실천 을 한다.
  • 좋은 웹페이지 즐겨찾기