에듀테크 프로젝트 대시보드
로프 자료구조 (Rope)
메모장에서 100MB짜리 로그 파일을 열고 맨 앞에 글자 하나를 넣으면 어떻게 될까?
문자열을 하나의 긴 배열로 저장하면 뒤의 1억 글자를 전부 한 칸씩 밀어야 한다(O(n)).
로프는 긴 문자열을 작은 조각(잎)으로 쪼개 이진 트리로 매달아 둔다.
각 내부 노드는 왼쪽 서브트리의 글자 수(weight)만 들고 있어서, i번째 글자 찾기도,
중간에 글자 넣기도 트리 높이 O(log n) 만에 끝난다. 큰 배열 복사가 사라진다.
파란 노드는 내부 노드(숫자 = weight, 왼쪽 서브트리 길이),
분홍 노드는 실제 글자를 담은 잎(leaf)이다.
삽입/삭제는 경계에 걸친 잎만 쪼개고 리스트를 잇는다 — 큰 문자열 복사 없음.
밑줄 _ 은 공백을 뜻한다.
루트에서 시작해 각 내부 노드에서 딱 한 번만 비교한다.
i < node.weight 이면 찾는 글자는 왼쪽 서브트리 안에 있다. 그대로 왼쪽으로 내려간다.
i ≥ node.weight 이면 오른쪽으로 가되, 왼쪽을 건너뛰었으니 i -= node.weight 로 좌표를 옮긴다.
잎에 닿으면 남은 i 로 leaf.text[i] 를 바로 반환. 방문 노드 수 = 트리 높이.
| 연산 | 평면 문자열 (배열) | 로프 (균형 트리) |
|---|---|---|
i번째 글자 읽기 charAt | O(1) | O(log n) |
중간에 삽입 insert | O(n) — 뒤 전체 밀기 | O(log n) |
중간 구간 삭제 delete | O(n) | O(log n) |
두 문자열 잇기 concat | O(n + m) 복사 | O(1) — 새 루트 하나 |
부분 문자열 substring | O(길이) 복사 | O(log n) — 조각 공유 |
| 메모리 지역성 / 캐시 | 연속 → 빠른 스캔 | 포인터 점프 → 조각화 |
| 구조 자체 오버헤드 | 없음 | 노드마다 포인터·weight |