Let's learn and try double-ended priority queue with Perl 6
오늘은 졸작 Algorithm::MinMaxHeap을 소개하고 싶습니다.
Introduction
Algorithm::MinMaxHeap은 double-ended priority queue의 구현입니다. [0]
하나의 나무 구조 안에, 내림차순과 오름차순의 2 종류의 힙이 동시에 들어가 있다는, 조금 재미있는 데이터 구조를 하고 있습니다.
좀 더 정확한 단어로 다시 말하면, 이것은 노드가 Min-Max 순서가 된 나무입니다.
MinMaxHeap Internals
대표적인 메소드(e.g. insert, pop)에 대해서, 내부에서 이러한 메소드가 실시하고 있는 것을 간단하게 설명합니다.
Min-Max 주문을 유지하면서 insert나 pop을 실시하기 위해서 아래와 같은 조작이 행해지고 있습니다. :
insert:
pop-max:
pop-min:
(※) 알기 쉽게 하기 위해서, 대략 간결하게 표현했습니다. 정확한 조작을 알고 싶다면 제대로 논문을 읽으십시오.
Let's try!
그럼, 실제로 사용해 봅시다.
가장 간단한 예를 소개하면 물론, 일반적으로 Int 형의 값을 노드로 한 double-ended priority queue를 만들 수 있습니다 :
basic.p6
use Algorithm::MinMaxHeap;
my Algorithm::MinMaxHeap[Int] $heap .= new;
my Int @items = (^10).pick(*);
@items.say; # [1 2 6 4 5 9 0 3 7 8]
$heap.insert($_) for @items;
$heap.pop-max.say; # 9
또한 subset을 사용하여 복잡한 유형 제약 조건을 직접 정의할 수도 있습니다.
아래의 예에서는 Cool 형의 서브 클래스로 Rat 나 Num 밖에 사용할 수 없다고 하는 제약의 ChimeraRat 형을 정의하고 있습니다.
chimera.p6
use Algorithm::MinMaxHeap;
my subset ChimeraRat of Cool where Num|Rat;
my Algorithm::MinMaxHeap[ChimeraRat] $heap .= new;
$heap.insert(10e0); # ok
$heap.insert(1/10); # ok
$heap.insert(10); # die
아래와 같이 Int형의 10을 대입했을 때에, 제대로 에러 메세지를 내고 종료할 수 있게 됩니다:
실행 결과
$ perl6 chimera.p6
Type check failed in assignment to @!nodes; expected ChimeraRat but got Int (10)
in method insert at /home/itoyota/.rakudobrew/moar-nom/install/share/perl6/site/sources/240192C19BBAACD01AB9686EE53F67BC530F8545 (Algorithm::MinMaxHeap) line 12
in block <unit> at 01.p6 line 8
사용자 정의 클래스의 인스턴스를 double-ended priority queue에 넣을 수도 있습니다.
class.p6
use Algorithm::MinMaxHeap;
my class State {
also does Algorithm::MinMaxHeap::Comparable[State];
has DateTime $.time;
has $.payload;
submethod BUILD(:$!time, :$!payload) { }
method compare-to(State $s) {
if $!time == $s.time {
return Order::Same;
}
if $!time > $s.time {
return Order::More;
}
if $!time < $s.time {
return Order::Less;
}
}
}
my State @items;
@items.push(State.new(time => DateTime.new(:year(1900), :month(6)),
payload => "Rola"));
@items.push(State.new(time => DateTime.new(:year(-300), :month(3)),
payload => "Taro"));
@items.push(State.new(time => DateTime.new(:year(1963), :month(12)),
payload => "Hanako"));
@items.push(State.new(time => DateTime.new(:year(2020), :month(6)),
payload => "Jack"));
my Algorithm::MinMaxHeap[Algorithm::MinMaxHeap::Comparable] $heap .= new;
$heap.insert($_) for @items;
$heap.pop-max.say until $heap.is-empty;
실행 결과
$ perl6 class.p6
State.new(time => DateTime.new(2020,6,1,0,0,0), payload => "Jack")
State.new(time => DateTime.new(1963,12,1,0,0,0), payload => "Hanako")
State.new(time => DateTime.new(1900,6,1,0,0,0), payload => "Rola")
State.new(time => DateTime.new(-300,3,1,0,0,0), payload => "Taro")
References
이상, 9일째의 투고, "Let's learn and try double-ended priority queue with Perl 6"이 되었습니다.
Reference
이 문제에 관하여(Let's learn and try double-ended priority queue with Perl 6), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/titsuki/items/1ad338c6cf14a59be3e8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)