더블 엔드 큐
Double-ended queue![]() | 이 기사는 대부분의 독자들이 이해하기에는 너무 전문적일 수 있다.. ( 4월 ( 템플릿메시지 및 ) 세부사항을 할 수 바랍니다 |
컴퓨터 과학에서 더블 엔드 큐(double-end queue, decue,[1] 발음 덱)는 큐를 일반화하는 추상 데이터 유형으로, 전면(헤드) 또는 후면([2]테일) 중 하나에 요소를 추가하거나 제거할 수 있습니다.이것은 종종 헤드테일 링크 리스트라고도 불리지만, 이는 deque의 특정 데이터 구조 구현을 의미합니다(아래 참조).
명명 규칙
데큐는 데큐로 쓰이기도 하지만, 데큐는 "큐에서 삭제하다"를 의미하는 동사이기도 하기 때문에 일반적으로 기술 문헌이나 기술 문서에서는 사용되지 않습니다.그럼에도 불구하고 몇몇 도서관과 교과서 데이터 구조와 알고리즘에 나오는 Aho, Hopcroft, Ulman과 같은 일부 작가들은 이것을 큐에서 제외합니다.Programming Languages의 Concepts의 저자 John Mitchell도 이 용어를 사용합니다.
구별 및 하위 유형
이는 요소를 한쪽 끝에만 추가하고 다른 쪽 끝에서는 제거할 수 있는 큐 추상 데이터 유형 또는 First In First Out List(FIFO; 선입선출 리스트)와는 다릅니다.이 일반 데이터 클래스에는 몇 가지 가능한 하위 유형이 있습니다.
- 입력 제한 디큐는 양끝에서 삭제할 수 있지만 삽입할 수 있는 것은 한쪽 끝뿐입니다.
- 출력 제한 디큐는 양끝에 삽입할 수 있지만 삭제할 수 있는 것은 한쪽 끝뿐입니다.
컴퓨팅, 큐 및 스택의 기본 및 가장 일반적인 목록 유형은 모두 데크의 전문화라고 간주할 수 있으며 데크를 사용하여 구현할 수 있습니다.
운용
디큐의 기본 조작은 enqueue와 양쪽 끝의 디큐입니다.또한 일반적으로는 큐를 제거하지 않고 해당 끝에서 값을 반환하는 Peek 작업도 구현됩니다.
이름은 언어에 따라 다릅니다.주요 실장은 다음과 같습니다.
작동 | 통용명 | 아다 | C++ | 자바 | 펄 | PHP | 파이썬 | 루비 | 녹 | 자바스크립트 |
---|---|---|---|---|---|---|---|---|---|---|
배면에 요소를 삽입하다 | 주입, 흡입, 푸시 | Append | push_back | offerLast | push | array_push | append | push | push_back | push |
요소를 전면에 삽입하다 | 푸시, 단점 | Prepend | push_front | offerFirst | unshift | array_unshift | appendleft | unshift | push_front | unshift |
마지막 요소 제거 | 이젝트하다 | Delete_Last | pop_back | pollLast | pop | array_pop | pop | pop | pop_back | pop |
첫 번째 요소를 제거하다 | 팝 | Delete_First | pop_front | pollFirst | shift | array_shift | popleft | shift | pop_front | shift |
마지막 요소를 조사하다 | 훔쳐보다 | Last_Element | back | peekLast | $array[-1] | end | <obj>[-1] | last | back | <obj>.at(-1) |
제1원소를 조사하다 | First_Element | front | peekFirst | $array[0] | reset | <obj>[0] | first | front | <obj>[0] |
실장
디큐를 효율적으로 구현하는 방법에는 적어도 두 가지가 있습니다.변경된 동적 배열과 이중 링크된 목록을 사용하는 방법입니다.
동적 어레이 접근법에서는 양단에서 확장할 수 있는 동적 어레이의 변형(어레이 디크라고도 함)을 사용합니다.이러한 어레이 디크는 일정 시간 랜덤 액세스, 양호한 기준 위치, 비효율적인 삽입/탈부착 등 동적 어레이의 모든 속성을 갖추고 있으며, 한쪽 끝에만 상각된 고정 시간 삽입/탈부착이 추가되어 있습니다.다음의 3가지 일반적인 구현이 있습니다.
- 디큐 콘텐츠를 원형 버퍼에 저장하고 버퍼가 가득 찼을 때만 크기를 조정합니다.이것에 의해, 사이즈 변경의 빈도가 감소합니다.
- 기본 어레이의 중앙에서 디큐 컨텐츠를 할당하고, 어느 한쪽 끝에 도달하면 기본 어레이의 크기를 조정합니다.이 접근방식은 특히 요소가 한쪽 끝에만 삽입되어 있는 경우 보다 빈번한 크기 조정과 더 많은 공간 낭비가 필요할 수 있습니다.
- 콘텐츠를 여러 개의 소규모 어레이에 저장하고 필요에 따라 처음 또는 끝에 추가 어레이를 할당합니다.인덱스는 각 작은 배열에 대한 포인터를 포함하는 동적 배열을 유지함으로써 구현됩니다.
순수하게 기능하는 구현
이중 엔드 큐는 순수하게 기능하는 데이터 [3]: 115 구조로도 구현할 수 있습니다.구현에는 두 가지 버전이 있습니다.첫 번째 '실시간 디큐'는 다음과 같습니다.O(1) 최악의 경우 큐의 동작을 영속적으로 유지할 수 있지만 메모화가 있는 지연 리스트가 필요합니다.두 번째 항목은 목록이나 메모가 없는 섹션의 끝에 제시되어 있습니다.영속성을 사용하지 않을 경우 상각된 시간은 O(1)입니다.단, 동작의 최악의 복잡도는 O(n)입니다.여기서 n은 더블 엔드 큐의 요소 수입니다.
다시 한 번 상기시켜 보자면l
, l
그 길이를 나타낸다.NIL
빈 목록을 나타냅니다.CONS(h, t)
헤드가 다음과 같은 목록을 나타냅니다.h
누구의 꼬리가t
.기능drop(i, l)
그리고.take(i, l)
명부를 반납하다l
첫 번째 없이i
요소 및 첫 번째 요소i
요소l
,각각 다음과 같다.또는 만약 l < i
빈 목록을 반환하고l
각각 다음과 같다.
느린 재구축과 스케줄링을 통한 실시간 개선
이중 엔드 큐는 6중으로 표시됩니다.(len_front, front, tail_front, len_rear, rear, tail_rear)
어디에front
길이 큐의 앞부분을 포함하는 링크 리스트입니다.len_front
.유사하게,rear
는 큐의 후면 길이를 나타내는 링크 리스트입니다.len_rear
또, front ≤ 2 rear +1
그리고. rear ≤ 2 front +1
- 직감적으로 말하면, 전면과 후면 모두 3분의 1에서 3분의 2까지의 요소를 포함하고 있는 것을 의미합니다.마침내.tail_front
그리고.tail_rear
의 뒷면front
및 의rear
에서는, 몇개의 느린 조작이 강제되는 순간을 스케줄 할 수 있습니다.주의: 더블 엔드 큐에 다음 명령어가n
전면 리스트의 요소 및n
뒤쪽 목록의 요소, 그러면 부등식 불변수는 다음 후에도 충족된 상태로 남습니다.i
삽입 및d
삭제 시(i+d) ≤ n/2
그것은 기껏해야n/2
동작은 각 재조정 사이에 발생할 수 있습니다.
먼저 deque - cons, head, tail에 영향을 미치는 다양한 작업의 구현을 설명하겠습니다.그러한 이행이 반드시 불변성을 존중하는 것은 아니다.두 번째 시간에는 불변성을 만족시키지 못하는 디큐를 그것을 만족시키는 디큐로 수정하는 방법을 설명할 것이다.그러나 전면이 비어 있으면 후면에는 최대 1개의 요소가 있다는 점에서 불변성을 사용합니다.목록의 뒷면에 영향을 미치는 작업은 대칭에 의해 유사하게 정의됩니다.
빈 = (0, 없음, 없음, 0, 없음, 없음) 재밌어요 삽입'(x, (len_front, 전선., 테일프런트, len_rear, 후미, 테일_리어)) = (len_front+1, 단점(x, 전선.), 떨어지다(2, 테일프런트), len_rear, 후미, 떨어지다(2, 테일_리어)) 재밌어요 머리((_, 단점(h, _), _, _, _, _)) = h 재밌어요 머리((_, 없음, _, _, 단점(h, 없음), _)) = h 재밌어요 테일'((len_front, 단점(정면, 전선.), 테일프런트, len_rear, 후미, 테일_리어)) = (len_front - 1, 전선., 떨어지다(2, 테일프런트), len_rear, 후미, 떨어지다(2, 테일_리어)) 재밌어요 테일'((_, 없음, _, _, 단점(h, 없음), _)) = 빈
방법을 정의하는 방법은 아직 설명되지 않았습니다.balance
디케의 균형을 재조정할 수 있는insert'
또는tail
불변수를 깨뜨렸다.방법insert
그리고.tail
처음에 적용함으로써 정의할 수 있다insert'
그리고.tail'
그 후 적용balance
.
재밌어요 균형.(q ~하듯이 (len_front, 전선., 테일프런트, len_rear, 후미, 테일_리어)) = 허락하다 플로어_half_len = (len_front + len_rear) / 2 에 허락하다 cale_half_len = len_front + len_rear - 플로어_half_len 에 한다면 len_front > 2*len_rear+1 그리고나서 허락하다 값 전면' = 가지고 가다(cale_half_len, 전선.) 값 후방' = 회전 드롭(후미, 플로어_half_len, 전선.) 에 (cale_half_len, 전면', 전면', 플로어_half_len, 후방', 후방') 또 다른 한다면 len_front > 2*len_rear+1 그리고나서 허락하다 값 후방' = 가지고 가다(플로어_half_len, 후미) 값 전면' = 회전 드롭(전선., cale_half_len, 후미) 에 (cale_half_len, 전면', 전면', 플로어_half_len, 후방', 후방') 또 다른 q
어디에rotateDrop(front, i, rear))
연결을 되돌리다front
및 의drop(i, rear)
.그것은front' = rotateDrop(front, ceil_half_len, rear)
에 넣다.front'
내용front
및 의 내용rear
아직 없는 것rear'
떨어트린 이후로n
요소에는 O O시간이 .각 요소에는 2개씩 드롭이 이루어지도록 게으름을 사용합니다.tail'
그리고 각각insert'
작동.
재밌어요 회전 드롭(전선., i, 후미) = 한다면 i < > 2 그리고나서 회전 리비전(전선., 떨어지다(i, 후미), $NIL) 또 다른 허락하다 $CONS(x, 전면') = 전선. 에 $CONS (x, 회전 드롭(전면', j-2, 떨어지다(2, 후미)))
어디에rotateRev(front, middle, rear)
는 전면을 반환하고, 중간을 반전하고, 그 다음에 후면을 반환하는 기능입니다.또한 이 함수는 게으름을 사용하여 정의되며, 각 함수가 실행되는 동안 한 단계씩 계산될 수 있습니다.insert'
그리고.tail'
시간이 많이 걸리는 것 같아요.이 함수는 다음과 같은 불변수를 사용합니다. rear -2 front
2 또는 3 입니다.
재밌어요 회전 리비전(없음, 후미, a)= 거꾸로 하다(후면 + + a) 재밌어요 회전 리비전(단점(x, 전선.), 후미, a)= 단점(x, 회전 리비전(전선., 떨어지다(2, 후미), 거꾸로 하다 (가지고 가다(2, 후미))++a))
어디에++
는 2개의 목록을 연결하는 함수입니다.
게으름 없는 구현
구현의 느린 부분이 없다면 이는 O(1)암호화 시간 내에 큐의 비영구적인 구현이 됩니다.이 경우 리스트는tail_front
그리고.tail_rear
는 더블 엔드 큐 표현에서 삭제할 수 있습니다.
언어 지원
Ada의 컨테이너는 범용 패키지를 제공합니다.Ada.Containers.Vectors
그리고.Ada.Containers.Doubly_Linked_Lists
다이내믹 어레이 구현 및 링크드 리스트 구현에 각각 사용됩니다.
C++의 표준 템플릿 라이브러리는 클래스 템플릿을 제공합니다.std::deque
그리고.std::list
다중 어레이 및 링크드 리스트의 각 실장은, 복수의 어레이와 링크드 리스트의 실장을 참조해 주세요.
Java 6에서 Java의 Collections Framework는 새로운 기능을 제공합니다.Deque
양쪽 끝에 삽입 및 분리 기능을 제공하는 인터페이스입니다.다음과 같은 클래스에 의해 구현됩니다.ArrayDeque
(Java 6에서도 새로운 기능) 및LinkedList
다이내믹 어레이와 링크드 리스트의 실장을 각각 제공합니다.하지만, 그ArrayDeque
는 이름과는 달리 랜덤액세스를 지원하지 않습니다.
Javascript의 Array 프로토타입과 Perl의 어레이는 양 끝에 (shift 및 pop) 요소를 제거하고 (unshift 및 push) 요소를 추가하는 기능을 기본적으로 지원합니다.
Python 2.4에서는collections
deque 객체를 지원하는 모듈.고정길이 서브어레이의 이중 링크 리스트를 사용하여 구현됩니다.
PHP 5.3에서 PHP의 SPL 확장에는 Deque 데이터 구조를 구현하기 위해 사용할 수 있는 'SplDoublyLinkedList' 클래스가 포함되어 있습니다.이전에는 어레이 함수 array_shift/unshift/pop/push를 대신 사용해야 했습니다.
GHC의 데이터시퀀스 모듈은 해스켈에 효율적이고 기능적인 디큐 구조를 구현합니다.구현에서는 크기가 주석으로 표시된 2~3개의 핑거 트리를 사용합니다.순수하게 기능하는(따라서 영속적인) 더블 큐(대부분은 매우 느린 [3][4]평가를 사용)를 실장할 수 있는 다른 (빠른) 방법이 있습니다.Kaplan과 Tarjan은 최적의 융합 지속적 catenable [5]dec를 최초로 구현했다.그들의 구현은 게으른 평가를 사용하지 않았다는 의미에서 순전히 기능적이었다.Okasaki는 부트스트래핑된 데이터 구조의 느린 평가를 사용하여 성능 한계를 최악의 경우에서 상각으로 낮춤으로써 데이터 구조를 단순화했습니다.Kaplan, Okasaki 및 Tarjan은 느린 평가를 사용하거나 더 광범위하지만 여전히 제한된 방식으로 돌연변이를 사용하여 보다 효율적으로 구현할 수 있는 보다 단순한 부트스트랩되지 않은 상각 버전을 제작했습니다.Mihaesau와 Tarjan은 순전히 기능적인 catenable dece의 구현과 완전히 순수하게 기능하지 않는 non-catenable dece의 구현이 보다 단순하게 이루어졌으며, 둘 다 최적의 최악의 경우 경계를 가지고 있다.
녹의std::collections
에는 확장 가능한 링 버퍼를 사용하여 더블 엔드 큐를 구현하는 VecDeque가 포함되어 있습니다.
복잡성
- 이중 링크 리스트의 실장에서는, 할당/해제 오버헤드가 없는 경우, 모든 디큐 동작의 시간 복잡도는 O(1)입니다.또, 중간에서의 삽입 또는 삭제의 시간 복잡도는, 반복자가 주어졌을 경우, O(1)이지만, 인덱스별 랜덤 액세스의 시간 복잡도는 O(n)이다.
- 증가하는 어레이에서 모든 디큐 작업의 상각된 시간 복잡도는 O(1)입니다.또한 인덱스별 랜덤 액세스의 시간 복잡도는 O(1)이지만 중간에 삽입 또는 삭제되는 시간 복잡도는 O(n)이다.
적용들

디큐를 사용할 수 있는 예로는 워크스틸 [6]알고리즘이 있습니다.이 알고리즘은 여러 프로세서에 대해 작업 예약을 구현합니다.프로세서별로 실행되는 스레드가 있는 별도의 디큐가 유지된다.다음 스레드를 실행하기 위해 프로세서는 디큐에서 첫 번째 요소를 가져옵니다("첫 번째 요소 제거" 디큐 작업을 사용).현재 스레드가 분기하면 데크('전방에 요소 삽입')의 전면에 다시 배치되어 새로운 스레드가 실행됩니다.프로세서 중 하나가 자체 스레드 실행을 완료하면(즉, deque가 비어 있음), 다른 프로세서에서 스레드를 "스틸"할 수 있습니다.다른 프로세서의 deque에서 마지막 요소("마지막 요소 제거")를 가져와 실행합니다.워크스틸 알고리즘은 인텔의 스레딩 빌딩 블록(TBB) 라이브러리에서 병렬 프로그래밍에 사용됩니다.
「 」를 참조해 주세요.
레퍼런스
- ^ 제시 리버티, 싯다르타 라오, 브래들리 존스C++, 하루에 1시간, Sams Teach Yourself, 제6판.샘스 출판사, 2009. ISBN0-672-3241-7.레슨 18: STL 다이내믹 어레이 클래스, 페이지 486.
- ^ 도널드 크누트.The Art of Computer Programming, Volume 1: Fundamental Algorithms, 제3판.애디슨 웨슬리, 1997년ISBN 0-201-89683-4.섹션 2.2.1: 스택, 큐, 디크, 페이지 238–243.
- ^ a b Okasaki, Chris (September 1996). Purely Functional Data Structures (PDF) (Ph.D. thesis). Carnegie Mellon University. CMU-CS-96-177.
- ^ 아담 L. 벅스바움과 로버트 E.타잔.데이터 구조 부트스트래핑을 통해 통합적으로 영속적인 디크.알고리즘 저널, 18(3): 513-547, 1995년 5월 (58, 101, 125페이지)
- ^ 하임 카플란과 로버트 E.타잔.catenable 정렬된 목록의 순수 기능 표현.컴퓨팅 이론에 관한 ACM 심포지엄, 202-211페이지, 1996년 5월 (4, 82, 84, 124)
- ^ Blumofe, Robert D.; Leiserson, Charles E. (1999). "Scheduling multithreaded computations by work stealing" (PDF). J ACM. 46 (5): 720–748. doi:10.1145/324133.324234. S2CID 5428476.