티스토리 뷰

반응형

Queue는 컴퓨터 과학에서 중요한 선입선출 자료구조 중 하나이다. 사실 큐의 일상 예시로 설명해 보면, 줄을 서는 개념과 비슷하다. 맛있는 마카롱 집을 가기 위해 줄을 선다고 해보자. 이 경우 먼저 줄을 선 사람이 먼저 마카롱을 사고, 나중에 온 사람이 나중에 마카롱을 사는 것과 같은 원리라고 할 수 있다. 이러한 Quere를 간단한 개념부터 시작해서, 선형 큐(Linear Queue) 원형 큐(Circlar Queue) 등등의 여러 방법으로 구현해 보자.

 

 


큐(Queue)

큐는 선입선출(FIFO : First-In-First-Out) 구조의 자료구조로 먼저 넣은 데이터를 먼저 꺼낸다. 이때, 먼저 데이터를 추가하는 작업을 인큐(enqueue)라고 하고, 데이터를 꺼내는 작업을 디큐(dequeue)라고 한다. 큐는 기본적으로 배열(Array)나 연결 리스트(Linked List)로 구현하는 것이 가능하다. 배열을 이용하여 구현한다면, 간단히 구현이 가능하지만 크기조정이 필요할 수가 있다. 그러나 연결 리스트를 사용하여 구현을 한다면 크기에 제약이 없고 동적으로 크기를 조정할 수 있어 편리하다. 이것은 일반적인 자료구조에서의 이야기이고 파이썬에서는 배열을 통해 Queue를 구현하면 굉장히 비효율적이다. 왜냐하면 배열(List)로 구현한 Queue는 dequeue 시 리스트의 앞쪽을 빼게 된다. 이러한 경우 리스트 내부의 전체 index 값이 한 칸씩 줄어들게 된다. 즉, 전체 메모리 위치가 변경시켜야 되기 때문에 느리다. 물론 Stack의 경우는 리스트의 오른쪽 부분의 데이터를 뺀다 각 데이터의 index값에는 별 문제가 없다. 정리하면, stack의 경우는 리스트로 구현을 해도 성능에 큰 차이가 없지만, 큐의 경우는 리스트로 구현 시 치명적인 속도문제가 발생하여 느려진다.

 

 

 

아래의 그림은 이해도를 높이기 위해 Queue에 enqueue와 dequeue를 그림으로 표현한 것이다.

made in hanpy
made in hanpy

 

그림을 통해 Queue라는 것은 한쪽 방향으로 데이터가 들어와서 다른 한쪽 출구로 데이터가 나가는 구조라는 것을 직관적으로 알 수 있다.

 

 


 

큐(Queue) 활용 사례

큐는 굉장히 많은 곳에서 다양하게 사용된다. 대표적인 활용 사례는 아래와 같다.

 

작업 스케줄링(Job Scheduling)

 운영 체제에서 프로세스의 실행을 관리할 때 큐를 사용한다. 준비 큐(Ready Queue)에 포함된 프로세스들이 들어온 순차적으로 실행하는 방식으로 작업 스케줄링이 진행된다.  멀티스레드 환경에서는 작업 큐(Job Queue)에 스레드 작업들을 추가한 순서대로 실행할 수 있도록 큐를 사용한다.

 

네트워크 패킷 처리(Network Packet Processing)

 네트워크 패킷은 인터넷상에서 데이터를 전송하는 단위이다. 데이터 전송 시 큰 데이터를 작은 조각으로 분할하여 패킷으로 만들고 이를 전송하게 된다. 이러한 패킷을 받을 때 큐에 저장하고, 순서대로 처리하여 패킷 손실을 방지하고 네트워크 효율을 향상한다.

 

멀티스레딩 환경(Multithreading)

 작업 스케줄링과 비슷하지만 조금 더 큰 개념이라고 불 수 있을 것 같다. 시스템에 포함되어 있는 자원들을 여러 프로세스나 스레드가 공유한다고 해보자. 자원에 대한 요청이 있을 시, 이 요청을 큐에 저장하고 순서대로 자원을 할당하는 방식으로 여러 프로세스나 스레스를 공평하게 자원을 사용할 수 있게 한다.

 

월 서버 요청 처리(Web Server Request Processing)

 웹 서버에서 클라이언트 요청 시, 받은 요청을 큐에 저장호고 순차적으로 처리하여 서버 과부하를 방지하고 응답 시간을 최소화한다.

 

캐시 관리(Cache Management)

 데이터의 접근 순서에 따라 큐에 저장하여 데이터를 효율적으로 관리하고 필요한 데이터를 빠르게 접근할 수 있도록 한다.

 

우선순위 치리(Priority Processing)

 일반적인 큐와는 약간 다르다. 일반 큐의 업데이트 버전이라 하면 된다. 각 작업에 우선순위를 부여하고, 관련 우선순위가 높은 작업을 먼저 처리하는 방식으로 큐를 사용한다. 쉽게 말하면, 큐에 넣는 방식은 동일하다. 그러나 큐에서 빼낼 시 우선순위가 높은 값을 먼저 빼내는 방식이라고 생각하면 된다.

 

너비 우선 탐색(Breadth-First Search)

 일명 BFS라는 너비 우선 탐색 시에도 큐를 사용한다. 탐색할 노드를 큐에 저장하고 순차적으로 방문하여 그래프를 탐색한다.

 

버퍼(buffer) 활용하기

버퍼란 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 데이터를 보관하는 메모리 영역이라 할 수 있다. 비슷한 의미로 버퍼링이란 버퍼를 활용하는 방식 또는 버퍼를 채우는 동작을 의미한다. 일반적으로 입출력 및 네트워크와 관련된 기능에서 많이 이용이 되고, 순차적으로 입력/출력이 전달되어야 하기 때문에 FIFO 방식의 자료구조인 큐가 활용된다.

 

 

 


 

큐(Queue) 구현하기

큐의 기본연산은 아래와 같다.

 

  1. 인큐(Enqueue): 큐의 뒤에 데이터를 추가합니다.
  2. 디큐(Dequeue): 큐의 앞에서 데이터를 제거하고 반환합니다.
  3. 프런트(Front) 확인: 큐의 앞에 위치한 데이터를 반환합니다. 제거하지 않습니다.
  4. 리어(Rear) 확인: 큐의 뒤에 위치한 데이터를 반환합니다. 제거하지 않습니다.
  5. 비어 있는지 확인(Is Empty): 큐가 비어 있는지 여부를 확인합니다.
  6. 큐의 크기 확인(Size): 큐에 저장된 데이터의 개수를 반환합니다.

 

위의 queue 기능을 하나씩 만들어보면 아래와 같다.

 

큐 생성하기

 

    def __init__(self):
        self.items = []

 

리스트로 큐를 만들어서 items에 넣어 주었다.

 

 

 

빈값 확인하기

 

    def isEmpty(self):
        if self.items == []:
            return True
        else:
            return False

 

리스트 내부에 값이 비어있는지 확인하여 Boolean 값을 리턴해 준다.

 

 

 

인큐(enQueue) 만들기

 

    def enqueue(self, item):
        self.items.append(item)

 

List의 append를 활용하여 인큐를 만들 수 있다.

 

 

 

디큐(deQueue) 만들기

 

    def dequeue(self):
        if len(self.items) != 0:
            return self.items.pop(0)
        else:
            print("Queue is empty")

 

pop(0)을 활용하여 내부의 값을 빼낼 수 있다.

 

 

 

큐 내부 확인하기

 

    def display(self):
        return (self.items)

 

items를 단순하게 리턴해주면 큐 값을 알 수 있다.

 

 

 

위 내용을 결합하여 Queue class를 만들면 아래와 같다.

 

class Queue:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        if self.items == []:
            return True
        else:
            return False

    def enqueue(self, item):
        self.items.append(item)

    def dequeue(self):
        if len(self.items) != 0:
            return self.items.pop(0)
        else:
            print("Queue is empty")

    def display(self):
        return (self.items)

if __name__ == "__main__":
    Q = Queue()
    Q.enqueue(1)
    Q.enqueue(2)
    Q.enqueue(3)
    Q.enqueue(4)
    Q.display()
    Q.dequeue()
    Q.dequeue()
    Q.dequeue()
    Q.display()

 

 

queue에서 pop(0)을 하면 안 쪽 데이터가 한 칸씩 당겨져서 느려진다. 따라서 insert와 pop을 쓰는 것을 지양하자. deque(덱)을 써라.

  • 덱은 내부적으로 list가 아니라 (Double Ended Queue) 링크드 리스트로 만들어져 있다. 지금 배우는 건 단순열결리스트고, 덱은 나중에 배울 이중연결 리스트로 만들어져 있다.
  • stack은 list의 가운데나 왼쪽을 넣고 뺄 필요 없이, 오른쪽 뒤 끝부분만 수정한다. 따라서 stack은 굳이 덱 쓸 필요 없이 list로 구현하면 된다.
  • Queue는 앞쪽을 빼므로 list로 쓰면 느려진다.

 

 

collections.deque 라이브러리르 이용하면, 간단히 stack을 구현할 수 있다.

from collections imort deque

class Stack:
    def __init__(self):
        self.items = deque([])

    def isEmpty(self):
        if len(self.items) == 0:
            return True
        else:
            return False

    def enqueue(self, item):
        self.items.append(item)

    def dequeue(self):
        if len(self.items) != 0:
            return self.items.pop()
        else:
            print("Stack is empty")

    def peek(self):
        if len(self.items) != 0:
            return self.items[len(self.items) - 1]
        else:
            print("Stack is empty")

    def display(self):
        return (self.items)

 

 


 

우선순위 큐

 

우선순위 큐는 아래와 같다. 우선순위 큐는 일반적인 큐와 동일하지만, 데이터를 넣는 부분만 다르다. 데이터를 넣을 때, priority(우선순위)를 비교해서 적절한 위치에 들어가게 된다. 아래의 def insert 부분을 보면, for 문을 통해 우선순위를 비교하여 0 인덱스부터 순차적으로 검사하여 추가하는 데이터의 우선순위보다 특정 인덱스의 우선순위가 큰 위치에 값을 넣어준다. 사실상 정렬 알고리즘 방식과 동일하다고도 할 수 있겠다.

 

class PriorityQueue:

    def __init__(self):
        self.queue = list()
        # if you want you can set a maximum size for the queue

    # O(n) insertion
    # Inserts new Node into the priority queue in increasing order of priority
    def insert(self, node):
        # if queue is empty
        if self.size() == 0:
            # add the new node
            self.queue.append(node)
        else:
            # traverse the queue to find the right place for new node
            for x in range(0, self.size()):
                # if the priority of new node is greater
                if node.priority >= self.queue[x].priority:
                    # if we have traversed the complete queue
                    if x == (self.size() - 1):
                        # add new node at the end
                        self.queue.insert(x + 1, node)
                    else:
                        continue
                else:
                    self.queue.insert(x, node)
                    return True

    # O(1) deletion
    def delete(self):
        # remove the first node from the queue
        return self.queue.pop(0)

    # Prints each element of the priority queue
    def show(self):
        for x in self.queue:
            print(str(x.info) + " - " + str(x.priority))

    # Returns the size of the priority queue
    def size(self):
        return len(self.queue)

 

우선순위 큐는 기본적인 큐와 다르게 list에 들어갈 값에 일반적인 정보뿐만 아니라, priority(우선순위정보)도 같이 넣어주는 것을 알 수 있다.

 


 

큐(Queue) 심화

큐에 대한 기초적인 정리는 완료하였다. 큐에 대한 구현을 다른 방법으로 진행해 보자. 구현방식은 front와 rear인 2개의 인덱스를 사용하여 구현해보려 한다. front 변수는 꺼내진 위치를 나타내고, rear 변수는 저장한 위치를 나타낸다. 처음에 자료가 아무것도 없는 상태라면 front와 rear 값이 -1로 초기화가 된다. 기본적으로 pointer를 사용하는 방법으로, 기존에 list를 사용할 때처럼 값을 빼도 list의 내부 값들이 한 칸씩 이동하는 방식은 적용되지 않았다.

 

데이터를 삽입하는 경우를 예를 들어 보겠다. 데이터 A를 넣으면 인덱스 0에 값이 들어가고 rear값은 0으로 변한다. 그리고 다시 데이터 B를 넣으면 인덱스 1 위치에 값이 들어가고 rear값을 1로 변한다. rear은 마지막 저장한 위치를 가리키는 것을 알 수 있다. 정리하면 큐 삽입의 경우는 front는 고정이고 rear 값만 변경되는 것을 확인할 수 있다.

 

데이터를 삭제하는 경우는 가장 먼저 삽입된 원소가 삭제된다. 위에서 넣었던 데이터 A가 삭제되고 front값은 0이 된다. 이때, 삭제라는 용어를 적었지만, list를 삭제한다기보다는 front 포인터를 옮겨서 삭제 부분을 나타낸다고 이해하면 더 좋을 것 같다. 다시 데이터 C를 넣으면, 1이었던 rear값은 2가 된다. 만약, 세 번의 삽입과 세 번의 삭제가 이루어진다면, Queue는 비어 있고, front와 rear 값은 둘 다 2로 같아진다고 할 수 있다. 즉 front와 rear가 같다면 Queue 비어있는 것이다.

 


 

선형 큐(Linear Queue)

이름에서 느껴지듯 선형 큐는 우리가 일반적으로 사용하는, 일자로 구성된 큐라고 할 수 있다. front와 rear 변수를 사용하는 포인터 자료구조를 활용해서 구현해 보자.

 

1. front : 저장된 첫 번째 원소의 인덱스로 마지막으로 꺼낸 자리를 의미한다.

2. rear : 저장된 마지막 원소의 인덱스로 마지막으로 저장된 자리를 나타낸다.

 

상태 표현은 초기 상태 / 공백 상태 / 포화 상태로 3가지로 나누어 구현을 할 예정이다.

  • 초기 상태 : front = rear = -1 (비어있어서 저장된 원소가 없음)
  • 공백 상태 : front = rear (연산 진행 중의 공백상태)
  • 포화 상태 : rear = n-1 (n: 리스트의 크기, n-1: 리스트의 마지막 자리 인덱스)
    • rear값이 큐의 마지막 위치 값이 되어있는 경우 큐가 가득 차있음
    • 포화 상태가 된 상태에서 데이터를 추가로 넣어야 될 상황이 벌어졌다면... Queue를 작게 만들었을 거다.. 즉, 문제 풀 때 포화 상태가 될 일은 없다.

 

구현 시 큐의 크기를 초반에 정해 놓고 하는 것이 좋다. 파이썬에서는 크기조정이 자동으로 되지만, 그래도 정해두고 하면 속도가 굉장히 빨라진다. 

 

초기 공백 큐 생성

 

q = [0]*3
front = -1
rear = -1

 

어렵게 class 쓸 필요 없이 단순하게 변수 지정으로 크기가 3인 큐를 list로 만들었다.

 

 

 

inEmpty(), isFull() 만들기

Queue에서는 삽입과 삭제를 위해서 큐가 가능 차있거나 비어있는지 상태를 확인할 필요가 있다.

 

def isEmpty():
    return front == rear
def isFull():
    return rear == len(Q)-1

 

 

isEmpty로 공백상태는 front와 rear가 같은 경우를 나타내고, 포화상태(isFull)는 rear = n-1 ( n이 리스트의 크기라면 n-1은 리스트의 마지막 인덱스를 가리킨다. )으로 확인가능하다. 공백상태인 경우에는 Ture반환하고, rear 값이 리스트의 마지막 인덱스 값이 되면 포화 상태가 되므로 True를 반환한다.

 

 

enQueue 만들기

마지막 원소 뒤에 새로운 원소를 삽입하기 위해서는 rear 값을 하나 증가시켜 새로운 원소를 삽입할 지리는 만든다. 그리고 그 자리에 해당하는 리스트 원소 Q [rear] 부분에 item을 저장한다.

 

def enQueue(item):
    global rear
    if isFull():          
        print("Queue_Full") 
    else:
        rear +=1
        Q[rear] = item

 

isFull 부분을 확인하는 이유는 큐가 가득 찬 상태에서는 더 이상 원소를 삽입할 수 없기 때문에 큐가 가득 차 있음을 알려주어야 하기 때문이다.

 

deQueue 만들기

가장 앞에 있는 원소를 삭제하기 위해서는 front 값을 하나 증가 시켜 큐에 남아있는 첫 번째 원소로 이동해야 한다. 새로운 첫 번째 원소를 리턴하여 삭제와 동일한 기능을 한다고 할 수 있다.

 

def deQueue(item):
    global rear
    if isEmpty():         
        print("Queue_Empty") 
    else:
        front +=1
        return Q[front]

 

큐가 비어있는 경우 더 이상 원소를 삭제할 수 없기 때문에 큐가 비어있음을 알려주어야 한다.

 

 

 

Qpeek() 만들기

 

가장 앞에 있는 원소를 검색하여 확인한다. 즉, 현재 front의 한자리 뒤(front+1)에 있는 원소, 즉 큐의 첫 번째에 있는 원소를 반환한다.

 

def Qpeek():
    if isEmpty() : 
        print("Queue_Empty")
    else:
        return Q[front+1]

 

큐가 비어있는지를 확인하고, 비어있으면 비어있다고 print 해준다. 여기 중요한 것은 front값은 변경되지 않는 것이다.

 

 

 

선형 큐(Linear Queue)의 단점

리스트의 크기를 동적으로 바꾸지 않고 고정하여 만든다는 것은 사용할 큐의 크기만큼 미리 확보를 해야 한다. 따라서 메모리 낭비가 발생할 수 있다. 선형 큐는 삽입, 삭제의 처리속도가 빠르다는 장점이 있지만, 메모리 낭비가 심하다는 단점도 있다. 삽입, 삭제를 계속할 경우 리스트의 앞부분에 활용할 수 있는 공간이 있음에도 rear=n-1 이 되어 포화 상태로 잘못 인식하여 더 이상의 삽입이 불가능해진다.

 

선형 큐를 해결하는 방법은 여러 가지가 있다. 기본적으로 메모리를 절약을 위해, list에서 데이터를 뺐을 때 앞으로 당기는 것(데이터의 인덱스 값들 변경)은 시간공간 낭비가 너무 심하므로 하면 안 된다. 따라서 큐 라이브러리를 사용해서 구현하거나, 단순 연결 리스트를 활용해서 메모리를 동적으로 확보하는 방식도 좋은 방법이라고 할 수 있다. 여러 방법들 중에 원형 큐(CIrclar Queue)를 만들어 선형 큐의 단점은 보안할 수 있다.

 


 

원형 큐(Circular Queue) 

원형 큐는 선형 큐의 문제점을 보안하기 위해 만들어진 자료구조라 고 할 수 있다. rear와 front가 가리키는 위치가 마지막 인덱스까지 가면, 그다음 인덱스는 0으로 갈 수 있도록 만든 것이 바로 원형 큐이다. 기본 리스트를 사용하는 것은 동일하지만, 원형을 반복하는 것과 같이 포이터를 이동시키는 것이라고 할 수 있다. 즉, 1차원 배열을 사용하지만 논리적으로는 배열을 처음과 끝이 연결되어 원형 형태의 큐를 이룬다고 가정하고 사용하는 것이다. (사실 원형 큐의 치명적인 문제는 가득 차면, 못쓴다. 쉽게 말하면, deQueue가 없이 큐가 가득 차게 되면 자료가 덮어쓰게 되어 원형 큐를 못쓰게 된다.)

 

 

원형 큐의 특징

초기 공백상태에서 원형 순환을 위해 front = rear = 0으로 설정되어 있다. 순환을 구현하기 위해서는, front와 rear의 위치가 리스트의 마지막 인덱스인 n-1을 가리킨다면, 논리적 순환을 위해 리스트의 처음 인덱스인 0으로 이동시켜야 한다. 이때 나머지 연산자 %를 사용하여 구현을 한다. front 변수는 공백 상태와 포화 상태 구분을 위해 front가 있는 자리를 사용하지 않고 항상 빈자리로 둔다. 선형 큐와의 차이점을 확인해 보면 아래와 같다.

 

테이블 인덱스 삽입 위치 삭제 위치
선형 큐 rear = rear + 1 front = front + 1
원형 큐 rear = (rear + 1) % n front = (front + 1) % n

 

원형 큐의 n이 넘어가면 n의 나머지를 구하여 위치를 재조정한다. 큐 생성 시 시작은 0에서 front와 rear이 시작하고, 인큐는 rear값이 1 증가하고 rear위치에 A를 삽입된다. 즉, 삽입이 0부터 되는 게 아니라 [1]부터 한다. 삭제는 front를 1 증가시키고 프런트위치의 A가 삭제한다.(실제 삭제는 아니고 덮어씌운다고 생각하면 된다.) 마지막 삽입은 [0]에도 가능하다. 예를 들면 크기가 4인 원형 큐에서 rear 값이 3이라면, 다음 삽입 위치는 0이 된다고 할 수 있다. 그리고 front위치에는 삽입 불가 하므로 front 빼고 삽입 다 됐으면 Full이라고 할 수 있다. 

 

 

isEmpty, isFull 만들기

공백 상태인 경우는 front = rear인 경우이다. 포화 상태인 경우는 선형큐와 다르게 삽입할 rear의 다음 위치가 현재 front 값일 때이다. 

 

def isEmpty():
    return front == rear

def isFull():
    return (rear+1) % len(cQ) == front

 

 

enQueue 만들기

마지막 윈소 뒤에 새로운 원소를 삽입하기 위하여 rear 값을 조정하여 새로운 원소를 삽입할 자리를 마련한다.(rear = (rear + 1) % n) 그리고 인덱스에 해당하는 리스트 원소를 저장한다. (Q[rear] = item

 

def enQueue(item):
    global rear
    if isFull:
        print("Queue_Full")
    else:
        rear = (rear+1)%len(cQ)
        cQ[rear] = item

 

enQueue에서 주의할 점은 큐가 가득 차 있지 않을 때만 수행한다.

 

 

deQueue

가장 앞에 있는 원소를 삭제하기 위해 front 값을 조정하여 삭제할 자리를 준비한다. 그리고 새로운 front 원소를 리턴하여 삭제와 동일한 기능을 하게 한다.

 

def deQueue():
    global front
    if isEmpty():
        print("Queue_Empty")
    else:
        front = (front+1)%len(cQ)
        return cQ[front]

 

front 값을 앞으로 이동시킬 때 나머지 연산을 수행하여 큐의 마지막 위치에 있는 경우 큐의 제일 앞으로 front값을 이동시킬 수 있다. 역시 큐가 비어있는 경우 알려주어야 한다.

 

 


 

연결 큐(Linked Queue) 구현하기

관련 이해를 위해서는 기본적으로 Linked list에 대한 이해가 필요하다. 확인을 하고 오면 아래의 내용을 쉽게 이해할 수 있을 것이다.

 

큐 생성하기

리스트 노드 없이 포인터 변수만 만들자. 아래와 같이 front와 rear는 None으로 초기화하자.

 

front = None
rear = None

 

 

isEmpty 만들기

def isEmpty():
    return front == None

 

공백상태를 확인하는 것은 간단히 None으로 확인이 가능하다.

 

 

enQueue 만들기

def enQueue(item):
    global front, rear
    newNode = Node(item) # 새로운 노드 생성
    if front == None: # 큐가 비어있으면
        front = newNode
    else:
        rear.next = newNode
    rear = newNode

 

새로운 노드를 생성 후에 데이터 필드에 item을 저장한다. 연결 큐가 공백이 아닌 경우와 공백인 경우에 따라 front, rear 변수를 지정하면 된다.

 

 

deQueue 만들기

def deQueue():
    global front, rear
    if isEmpty():
        print("Queue_Empty")
        return None

    item = front.item
    front = front.next
    if front == None:
        rear = None
    return item

 

간단히 front를 다음 front를 가리키게 하고, 현재 front의 item을 리턴해주면 간단히 구현이 가능하다.

 

 

Linked Queue 테스트하기

아래의 코드를 통해 구현하는 것이 가능하다.

class Node:
    def __init__(self, item, n = None):
        self.item = item
        self.next = n
# 노드안에 item과 node을 만듬.


def enQueue(item):
    global front, rear
    newNode = Node(item) # 새로운 노드 생성
    if front == None: # 큐가 비어있으면
        front = newNode
    else:
        rear.next = newNode
    rear = newNode

def isEmpty():
    return front == None

def deQueue():
    global front, rear
    if isEmpty():
        print("Queue_Empty")
        return None

    item = front.item
    front = front.next
    if front == None:
        rear = None
    return item

def Qpeek():
    return front.item

def printQ():
    f = front
    s = ""
    while f:
        s += f.item + " "
        f = f.next
    return s

front = None
rear = None

enQueue('A')
enQueue('B')
enQueue('C')
printQ()
print(deQueue())
print(deQueue())
print(deQueue())

 

 

 

 

 

정리

사실 Queue는 매우 중요하다. 그리고 위의 정보뿐만 아니라 다른 다양한 큐도 존재한다. 조금 관심이 든다면, 큐에 대해 공부해 보는 것도 좋다는 생각이 든다. 사실 BFS 문제 풀이 부분까지 넣으려 했으나, 글이 너무 길어져서 관련 내용은 다른 글에서 다뤄보도록 하겠다.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함