O (N log N) 복잡성-선형과 유사합니까?


78

그래서 사소한 질문을해서 묻히게 될 것 같은데 뭔가 좀 헷갈려요.

Java와 C로 퀵 정렬을 구현했으며 몇 가지 기본적인 비교를 수행했습니다. 그래프는 2 개의 직선으로 나 왔으며 C는 100,000 개의 임의 정수를 통해 Java보다 4ms 더 빠릅니다.

결과

내 테스트 코드는 여기에서 찾을 수 있습니다.

android-benchmarks

(n log n) 선이 어떻게 생겼는지 확신 할 수 없었지만 직선이라고 생각하지 않았습니다. 나는 이것이 예상 된 결과이고 내 코드에서 오류를 찾으려고하지 않아야한다는 것을 확인하고 싶었습니다.

나는 공식을 엑셀에 집어 넣었고 10 진법의 경우 처음에는 꼬임이있는 직선 인 것 같습니다. log (n)과 log (n + 1)의 차이가 선형 적으로 증가하기 때문입니까?

감사,

Gav


1
Google 이미지 검색은 "n log n"과 같은 검색에서 놀랍게도 좋은 것 같습니다.
Tom Hawtin-tackline 2009-06-08

1
맨 위에있는 Java 라인은 나에게 똑바로 보이지 않습니다.
Puppy

실제로 유사합니다. 이것이 "선형 시간"
msanford 2013

답변:


81

그래프를 더 크게 만들면 O (n logn)이 직선이 아니라는 것을 알 수 있습니다. 그러나 예, 선형 동작에 매우 가깝습니다. 그 이유를 알아 보려면 아주 큰 수의 로그를 취하십시오.

예 (10 진수) :

log(1000000) = 6
log(1000000000) = 9
…

따라서 1,000,000 개의 숫자를 정렬하기 위해 O (n logn) 정렬은 measly factor 6을 추가합니다 (또는 대부분의 정렬 알고리즘이 base 2 로그에 의존하기 때문에 조금 더). 끔찍하지 않습니다.

사실,이 로그 요인이다 그래서 크기의 대부분의 주문에 대한 설립 O (N logn) 알고리즘은 선형 시간 알고리즘을 능가하는 것이 매우 작은. 대표적인 예는 접미사 배열 데이터 구조의 생성입니다.

최근에 기수 정렬을 사용하여 짧은 문자열의 퀵 정렬 정렬을 개선하려고 할 때 간단한 사례가 나를 물었습니다 . 짧은 문자열의 경우이 (선형 시간) 기수 정렬이 빠른 정렬보다 빠르지 만 기수 정렬은 정렬하는 문자열의 길이에 따라 결정적으로 달라지기 때문에 여전히 상대적으로 짧은 문자열에 대한 티핑 포인트가있었습니다.


1
좋은 정렬은 일단 분할되고 충분히 작은 조각으로 정복되면 선형 알고리즘을 사용하는 경향이 있습니다. 벤치마킹 (실제 데이터)의 문제가 정확히 얼마나 작은 지.
Tom Hawtin-tackline 2009-06-08

2
Tom : 선형이 정확히 무엇을 의미하는지 잘 모르겠습니다. 종종 정렬 알고리즘은 작은 부분에 대한 삽입 정렬과 같은 O (n ^ 2) 정렬을 사용하여 그 반대를 수행합니다. 상수 계수가 너무 작아서 2 차 런타임도 nlogn 정렬보다 성능이 우수하기 때문입니다. 반면에, introsort는 너무 깊은 재귀에서 벗어나기 위해 전략을 사용합니다. 그러나 다시 말하지만 이것은 선형적인 것이 아니라 O (n logn) 동작에 대한 4 차 최악의 경우를 교환합니다.
Konrad Rudolph

11

참고로 quicksort는 실제로 O (n ^ 2)이지만 평균적인 경우는 O (nlogn)입니다.

참고로, O (n)과 O (nlogn) 사이에는 상당히 큰 차이가 있습니다. 그것이 어떤 상수에 대해서도 O (n)에 의해 제한되지 않는 이유입니다.

그래픽 데모는 다음을 참조하십시오.

O (n) 대 O (nlogn)


2
a) 지정하지 않고 O ()는 일반적으로 예상되는 (평균) 복잡성 을 나타내는 데 사용됩니다 . b) O () 표기법은 상수 인자를 포함하지 않으므로 O (n)과 O (2n)은 동일합니다. log (n)은 거의 일정하기 때문에 (n에 비해 큰 수의 경우) O (n)과 O (n log (n))은 거의 같다고 말할 수 있습니다. 플롯해야합니다. wolframalpha.com/input/?i=plot+7+x%2C+x+log+x+from+1+to+1500
Timmmm

13
이것은 일반적으로 사실이 아닙니다. Big O 표기법은 일반적으로 최악의 점근 복잡성을 나타내며 알고리즘 복잡성을 초과하는 함수를 표시합니다. O (n)은 O (nlogn)의 근사치가 아니지만 실용적인 목적으로 O (nlogn)은 상대적으로 좋고 나쁘지는 않습니다. 빠른 정렬의 최악의 경우 성능은 확실히 드문 일이 아닙니다 . 나를 믿지 않는다면 사전에있는 항목에 대해 빠른 정렬을 시도하십시오.
groundhog

큰 차이는 없습니다. 특히 다음 주문 $ O (n ^ 2) $와 비교할 때. i.sli.mg/9zXUQR.png
Isopycnal Oscillation

5

비슷한 맥락에서 더 재미있게 보려면 표준 분리 집합 데이터 구조 에서 n 작업에 걸리는 시간을 플로팅 해보십시오 . 그것은 점근 적으로 n  α ( n ) 로 나타났습니다. 여기서 α ( n )은 Ackermann 함수 의 역입니다 (일반 알고리즘 교과서는 아마도 n log log n 또는 아마도 n log * n 의 경계 만 표시 할 것입니다 ). 입력 크기로 접할 수있는 모든 종류의 숫자에 대해 α ( n ) ≤ 5 (실제로 log *  n  ≤ 5)이지만 점근 적으로 무한에 접근합니다.  

여기서 배울 수 있다고 생각하는 것은 점근 적 복잡성이 알고리즘에 대해 생각하는 데 매우 유용한 도구이지만 실제 효율성과는 전혀 다르다는 것입니다.


3
  1. 일반적으로 O (n * log (n)) 알고리즘에는 2베이스 로그 구현이 있습니다.
  2. n = 1024 인 경우 log (1024) = 10이므로 n * log (n) = 1024 * 10 = 10240 계산, 한 배 증가합니다.

따라서 O (n * log (n))는 소량의 데이터에 대해서만 선형과 유사합니다.

팁 : quicksort는 임의의 데이터에서 매우 잘 작동하며 O (n * log (n)) 알고리즘이 아님을 잊지 마십시오.


3
모든 로그는 동일하며 규모 만 다릅니다. 그래서 나는 당신의 첫 번째 진술의 중요성을 보지 못합니다. 또한 O (n log n)은 소량의 데이터에 대해 선형과 유사하다는 귀하의 진술에 동의하지 않습니다. 다시 한 번, 확장 문제입니다. 반례로, 원래 질문의 그래프를보십시오.
waxwing

그래픽 적으로는 비슷하지만 (직선으로) 시간 복잡성은 비슷합니다. O (n logn) 시간은 쉽게 O (n)보다 10 배 더 클 수 있습니다. 그래프가 O (n logn) 및 O (n) 알고리즘을 비교하면 내가 의미하는 바를 알 수 있습니다. :) N이 점점 커질수록 O (n logn) *는 다음 로그 스케일로 이동 합니다.
Nick Dandoulakis

1
평균적으로 Quicksort는 O (n log n) 알고리즘입니다.
Manu

@waxwing이 말한 것처럼 첫 번째 요점은 잘못되었습니다. 서로 다른 기저의 한계를 나눔으로써 로그 기저를 변경하면 복잡성이 상수 요인에 의해서만 영향을 받는다는 것을 증명할 수 있습니다. 로그 기저는 복잡성 관점에서 관련이 없습니다. 결론적으로, 요소의 수가 증가함에 따라 선형 및 로그 선형 선의 모양이 더 비슷해집니다.
mateor

2

축이 올바르게 선택되면 모든 데이터를 선에 그릴 수 있습니다. :-)

Wikipedia는 Big-O가 최악의 경우라고 말합니다 (예 : f (x)는 O (N)는 f (x)가 N에 의해 ​​"위에 속함"을 의미 함) https://en.wikipedia.org/wiki/Big_O_notation

다음은 다양한 공통 기능 간의 차이점을 보여주는 멋진 그래프입니다. http://science.slc.edu/~jmarshall/courses/2002/spring/cs50/BigO/

log (x)의 미분은 1 / x입니다. x가 증가함에 따라 log (x)가 얼마나 빨리 증가하는지입니다. 너무 느리게 구부러지기 때문에 직선처럼 보일 수 있지만 선형은 아닙니다. O (log (n))를 생각할 때, 나는 그것을 O (N ^ 0 +), 즉 N의 양의 상수 거듭 제곱이 결국 그것을 추월 할 것이기 때문에 상수가 아닌 N의 가장 작은 제곱이라고 생각합니다. 100 % 정확하지 않으므로 그렇게 설명하면 교수님이 화를 낼 것입니다.

서로 다른 두 염기의 로그 차이는 상수 승수입니다. 두 염기 사이에서 로그를 변환하는 공식을 찾으십시오. (여기 "기본 변경"아래 : https://en.wikipedia.org/wiki/Logarithm ) 트릭은 k와 b를 상수로 취급하는 것입니다.

실제로 플로팅하는 데이터에는 일반적으로 약간의 딸꾹질이 있습니다. 프로그램 외부의 것에는 차이가 있습니다 (프로그램보다 먼저 CPU로 스와핑되는 것, 캐시 미스 등). 신뢰할 수있는 데이터를 얻으려면 많은 실행이 필요합니다. 상수는 Big O 표기법을 실제 런타임에 적용하려는 가장 큰 적입니다. 높은 상수를 가진 O (N) 알고리즘은 N이 충분히 작은 경우 O (N ^ 2) 알고리즘보다 느릴 수 있습니다.


(나는 당신이 곡선의 일반적인 용어로 "선"이 아니라 직선을 의미한다고 가정하고 있습니다.) 저는 연속적으로 미분 할 수있는 실제 변수의 실수 값 함수가 축이 직선에 그려 질 수 있다고 생각합니다. 중복 축 값 (일대일 함수가 아닌 경우 필요)과 같은 중간 정도의 허위만으로 올바르게 선택되지만 "모든 데이터"? 나는 그것이 스트레칭이라고 생각합니다. 모든 유리수에 대해 0이지만 모든 비합리 수에 대해 1 인 함수는 어떻습니까? (디리클레 함수로 알려져 있으며 진정한 수학적 함수입니다.)
Sarah G

1

log (N)은 (매우) N의 자릿수입니다. 따라서 대부분의 경우 log (n)과 log (n + 1) 사이에는 거의 차이가 없습니다.


3
log-base- 10 은 대략 N의 자릿수입니다 (10 진수 표현을 사용한다고 가정). 대부분의 정렬 / 검색 알고리즘은 log-base-2를 사용합니다. 이는 log-base-10에 비례하지만 (따라서 big-O가 여전히 적용됨) 설명하는 것과는
다릅니다.

또 다른 말은 log-base-2는 이진수로 쓰여졌을 때 N의 자릿수, 즉 N을 나타내는 데 필요한 비트 수라는 것입니다.
Tyler McHenry

0

그 위에 실제 선형 선을 그려 보면 작은 증가를 볼 수 있습니다. 50,0000의 Y 값은 100,000의 1/2 Y 값보다 작습니다.

거기에 있지만 작습니다. 이것이 O (nlog (n))이 좋은 이유입니다!


여전히 O (n ^ 2)보다 더 나은 광경입니다.
paxdiablo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.