[CS] Python의 pop(0)와 Java의 remove(0)

khj·2025년 2월 12일

Computer Science

목록 보기
20/25
post-thumbnail

1. 리스트 기반 큐 구현과 pop(0) 문제

큐(Queue)는 FIFO(First In, First Out) 구조를 가지며, 일반적으로 enqueue(추가)와 dequeue(제거) 연산을 수행합니다.
Python에서 list.pop(0)을 사용해 큐의 맨 앞 요소를 제거할 수 있지만, 이는 비효율적인 연산입니다.

queue = [1, 2, 3, 4, 5]
queue.pop(0)  # 첫 번째 요소(1) 제거
print(queue)  # [2, 3, 4, 5]

이 과정에서 리스트의 모든 요소가 한 칸씩 이동하므로 O(n) 시간 복잡도가 발생합니다.

2. Python 리스트의 내부 구조와 pop(0) 성능

Python의 list는 동적 배열(dynamic array) 로, 연속된 메모리 공간을 사용합니다.
즉, pop(0)이 호출되면 내부적으로 다음 과정이 발생합니다.

  1. 첫 번째 요소 제거
  2. 나머지 요소를 왼쪽으로 한 칸씩 이동
  3. 필요할 경우 메모리 재할당

📌 결과적으로 pop(0)은 O(n) 시간 복잡도를 가짐

연산 연산 방식 시간 복잡도
append(x) 리스트 끝에 요소 추가 O(1)
pop() 리스트 끝 요소 제거 O(1)
pop(0) 리스트 앞 요소 제거 O(n)

3. Java ArrayList와의 비교

Python 리스트와 유사한 Java의 ArrayList도 배열 기반 자료구조이므로 remove(0) 연산 시 동일한 문제를 가집니다.

List<Integer> queue = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
queue.remove(0);
System.out.println(queue);  // [2, 3, 4, 5]

remove(0) 호출 시 배열 요소 이동이 필요하여 O(n) 시간 복잡도가 발생합니다.

4. 효율적인 대안

pop(0)을 피하려면 연결 리스트(Linked List) 구조나 양쪽 끝에서 빠르게 요소를 추가/제거할 수 있는 자료구조를 고려해야 합니다.


4.1 리스트 끝을 활용한 대체 방식 (pop() 사용)

리스트의 끝에서 요소를 제거하는 pop()은 O(1) 연산이므로 빠릅니다.
하지만, 큐(Queue)의 FIFO 원칙을 깨고 LIFO(Stack) 방식으로 동작하게 되므로 주의해야 합니다.

queue = [1, 2, 3, 4, 5]
queue.pop()  # O(1), 하지만 LIFO 방식(Stack) 동작

4.2 연결 리스트(Linked List) 활용

Python의 기본 list는 배열 기반이므로 pop(0)이 느리지만, 연결 리스트를 사용하면 O(1) 시간 복잡도로 앞에서 요소를 제거할 수 있습니다.
직접 연결 리스트를 구현하면 다음과 같습니다.

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

class Queue:
    def __init__(self):
        self.head = None
        self.tail = None

    def enqueue(self, value):
        new_node = Node(value)
        if self.tail:
            self.tail.next = new_node
        self.tail = new_node
        if not self.head:
            self.head = new_node

    def dequeue(self):
        if not self.head:
            return None
        value = self.head.value
        self.head = self.head.next
        if not self.head:
            self.tail = None
        return value

queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)

print(queue.dequeue())  # 1
print(queue.dequeue())  # 2

🔹 시간 복잡도:

  • enqueue() → O(1)
  • dequeue() → O(1)
    배열 기반 리스트보다 효율적으로 큐를 구현할 수 있음.

4.3 리스트 슬라이싱(list = list[1:])을 사용하지 않는 이유

queue = [1, 2, 3, 4, 5]
queue = queue[1:]  # 첫 번째 요소 제거 후 새로운 리스트 생성

이 방식은 pop(0)을 대체할 수 있지만, 새로운 리스트를 생성하므로 시간 복잡도가 O(n) 이며 메모리 사용량이 증가하는 문제가 있습니다.
따라서 더 비효율적인 방법입니다.

profile
Spring, Django 개발 블로그

0개의 댓글