join
Unix 명령의 복잡성을 아는 사람이 있는지 궁금합니다 . 두 파일을 모두 정렬해야 하기 때문에 선형일 수 있다고 가정합니다.
어떤 사람들은 그것이 대수적이라고 주장하는데, 나는 그것이 의심스럽습니다. 아니면 파일에 따라 다르며 N*log(N)
파일 중 하나가 더 작을 때 로그(또는)일 수 있고 두 파일이 모두 크면 선형에 가까울 수 있습니까?
답변1
BSD join
구현은 따르기가 매우 쉽고 파일의 줄 수에 따라 선형적으로 확장되는 것 같습니다. 이는 최소한 BSD 4.4 Lite2부터 모든 BSD 시스템에서 본질적으로 변경되지 않았습니다. 다음 스 니펫은현재 OpenBSD 시스템, 비교하려고,다음은 BSD 4.4 Lite2 코드에 대한 링크입니다.원래 1991년 Keith Bostic이 제출한 것입니다(이 유틸리티의 이전 버전을 대체함).
/*
* We try to let the files have the same field value, advancing
* whoever falls behind and always advancing the file(s) we output
* from.
*/
while (F1->setcnt && F2->setcnt) {
cval = cmp(F1->set, F1->joinf, F2->set, F2->joinf);
if (cval == 0) {
/* Oh joy, oh rapture, oh beauty divine! */
if (joinout)
joinlines(F1, F2);
slurp(F1);
slurp(F2);
}
else {
if (F1->unpair
&& (cval < 0 || F2->set->cfieldc == F2->setusedc -1)) {
joinlines(F1, NULL);
slurp(F1);
}
else if (cval < 0)
/* File 1 takes the lead... */
slurp(F1);
if (F2->unpair
&& (cval > 0 || F1->set->cfieldc == F1->setusedc -1)) {
joinlines(F2, NULL);
slurp(F2);
}
else if (cval > 0)
/* File 2 takes the lead... */
slurp(F2);
}
}
내가 찾고 있어요join
GNU coreutils의 코드, 그러나 GNU 코드에는 내가 할 수 있는 것이 너무 많습니다.추측하다, 코드의 주석에 따르면 거의 동일한 유형의 알고리즘을 구현합니다.
/* Keep reading lines from file1 as long as they continue to
match the current line from file2. */
[...]
/* Keep reading lines from file2 as long as they continue to
match the current line from file1. */
[...]
정렬을 고려하고 정렬 알고리즘을 가정하면 값이 클수록 N*log(N)
전체 시간 복잡도는 N*(1 + log(N))
or가 됩니다. 즉, JOIN 작업이 정렬보다 빠릅니다.N*log(N)
N
JOIN 작업을 사용하면 행을 건너뛸 수 없기 때문에 선형 작업보다 더 나은 작업을 수행할 수 없습니다(일부 설명에 대한 미리 계산된 인덱스가 있고 시간 복잡도에 인덱스를 포함하지 않는 경우). 가장 좋은 경우는 연결된 줄이 없다는 것입니다. 이 경우 두 파일 중 하나에서 모든 줄을 읽고 이를 다른 파일의 첫 번째 줄과 비교해야 합니다. 최악의 경우는 모든 행이 연결되는 것입니다. 이 경우 두 파일을 모두 읽고 두 행 집합 간에 쌍별 비교를 수행해야 합니다(정렬된 파일에 대한 선형 연산). 사용자가 짝이 없는 줄을 보라고 요청하면 두 파일을 모두 완전히 읽어야 합니다.
선형 JOIN만 사용하는 것보다 더 나쁜 작업을 수행한다면 잘못된 작업을 수행하는 것입니다.