SORU
6 AĞUSTOS 2008, ÇARŞAMBA


Büyük O, nasıl/yaklaşık hesaplamak mı?

CS mezunu olan çoğu kişi, kesinlikle Big O stands forbilir. Ölçmek için bir algoritma gerçekten ve eğer what category the problem you are trying to solve lays in Eğer hala mümkünse biraz daha fazla performans sıkmak için ise bir yolunu biliyorsan nasıl (verimli)için bize yardımcı olur.1

Ama merak ediyorum, nasılsanahesaplamak algoritmaların karmaşıklığını yaklaşık?

1ama dedikleri gibi, aşırıya kaçmayın, premature optimization is the root of all evil ve haklı bir neden olmadan optimizasyon bu ismi de hak ediyor.

CEVAP
31 Ocak 2011, PAZARTESİ


Bir profesör Yapıları ve Algoritmalar ders Veri benim yerel üniversitede asistan oldum. Benim en iyi burada basitçe açıklamak için elimden geleni yapacağım, ama bu konu benim öğrenci alır uyardı nihayet kavramak için bir kaç ay. Data Structures and Algorithms in Java kitabın Bölüm 2'de daha fazla bilgi bulabilirsiniz.


Bu BigOh almak için kullanılabilir mechanical procedure yoktur.

Bir "yemek kitabı", elde etmek için BigOh bir parça kod ilk ihtiyacı fark vardır oluşturarak bir matematik formülü kadar say kaç adım hesaplamaları olsun idam verilen bir giriş bazı boyutu.

Amaç basit: kodu çalıştırmak için gerek kalmadan bakış teorik açıdan bakıldığında,. algoritmaları karşılaştırmak için Adım sayısı, daha hızlı algoritma daha az.

Örneğin, bu kod parçası var:

int sum(int* data, int N) {
    int result = 0;               // 1

    for (int i = 0; i < N; i  ) { // 2
        result  = data[i];        // 3
    }

    return result;                // 4
}

Bu işlev, dizinin tüm elemanlarının toplamını verir, ve bu işlevi computational complexity sayısı için bir formül yaratmak istiyoruz:

Number_Of_Steps = f(N)

f(N), hesaplama adımları saymak için bir işlevi var. Fonksiyonun giriş işlemi için yapı boyutudur. Bu işlev suchs olarak: denir anlamına gelir

Number_Of_Steps = f(data.length)

Parametre N data.length değerini alır. Şimdi işlevi gerçek tanımı f() ihtiyacımız var. Bu 4'e 1 gelen her ilginç hat numaralı kaynak kodu, yapılır.

Bu BigOh hesaplamak için birçok yol vardır. Bu noktadan giriş verileri büyüklüğüne bağlı olmayan her cümle C sabit bir sayı hesaplama adım atıyor varsayıyoruz.

Fonksiyonun adımları tek tek numara eklemek için gidiyoruz, ve ne yerel değişken bildirimi ne return ifadesi data dizinin boyutu bağlıdır.

Bu hat 1 ve 4 C adımları her miktar alır, ve bu şekilde biraz anlamına gelir:

f(N) = C   ???   C

Sonraki bölüm for ifadesinin değeri tanımlamak için. Hesaplamalı adım sayısını ifade bedeni N kez idam alır, diğer bir deyişle sayma olduğunu unutmayın. *,* 27 ** 26 defa ekleme de aynen şu şekilde:

f(N) = C   (C   C   ...   C)   C = C   N * C   C

for vücut infaz ediliyor, bu kodu tam olarak ne yaptığını bakarak saymak gerekir nasıl saymak için mekanik bir kural yok. Hesaplamaları basitleştirmek için for deyimi değişken başlatma, koşul ve artım parçaları göz ardı edilmektedir.

İşlevi Asymptotic analysis ihtiyacımız olan gerçek BigOh almak için. Bu böyle yapılır kabaca:

  1. Tüm sabitleri 31**.
  2. f() standard form polynomium.
  3. Bu polynomium şartları böl ve büyüme oranına göre sıralamak.
  4. N infinity yaklaştığında daha büyük büyüyen bir tutmak.

f() bizim iki dönem vardır:

f(N) = 2 * C * N ^ 0   1 * C * N ^ 1

C sabitler ve yedek parçaları tüm götürüp:

f(N) = 1   N ^ 1

Son bir terim, büyüdükçe daha büyük olduğunda f() yaklaşımlar sonsuz (sanırım limits) bu BigOh argüman, ve sum() fonksiyona sahip bir BigOh:

O(N)

Bazı zor olanları çözmek için birkaç hile vardır: istediğiniz zaman kullanın. summations. summation identities bazı kullanışlı zaten doğru olduğu kanıtlanmıştır.

Başka bir örnek olarak, bu kod toplamları kullanılarak kolayca çözülebilir:

for (i = 0; i < 2*n; i  = 2) {  // 1
    for (j=n; j > i; j--) {     // 2
        foo();                  // 3
    }
}

Sorulması için gerekli olan ilk şey foo() yürütme sırası. Her zamanki gibi O(1) olması ise bu konuda profesörler sormak gerekir. O(1) (neredeyse çoğu) sabit 47 ** N bağımsız anlamına gelir.

Bu cümle üzerinde for deyimi numaralı zordur. Endeksi 2 * N, biter ise artış iki tarafından yapılır. İlk for N adım idam olur, ve iki tarafından sayısını bölmek gerekir.

f(N) = Summation(i from 1 to 2 * N / 2)( ... ) = 
     = Summation(i from 1 to N)( ... )

Cümle sayısıikii değeri bağlıdır beri. daha komplikedir Bak: dizin alır değerleri: 0, 2, 4, 6, 8, ..., 2 * N ve ikinci for idam: N kez birinci, N - 2 İkinci, N - 4 üçüncü... N / 2 evre, ikinci for asla idam alır.

Formül, anlamına gelir:

f(N) = Summation(i from 1 to N)( Summation(j = ???)(  ) )

Yine, geri sayım devam ediyoradım sayısı. Ve tanımı gereği, her toplamı her zaman en başlatın ve bir numara daha büyük veya eşit en sonunda.

f(N) = Summation(i from 1 to N)( Summation(j = 1 to (N - (i - 1) * 2)( C ) )

(foo() O(1) C adım atıyor varsayıyoruz.)

i değer N / 2 1 Yukarı alır, iç Toplamı negatif bir sayı biter! bir sorunumuz var: Bu imkansız ve yanlış. Toplam bölünmüş iki, an N / 2 1 alır önemli nokta olmak istiyoruz.

f(N) = Summation(i from 1 to N / 2)( Summation(j = 1 to (N - (i - 1) * 2)) * ( C ) )   Summation(i from 1 to N / 2) * ( C )

Önemli anlardan beri i > N / 2, iç infaz etmeyecek ve gövde üzerinde sabit C yürütme karmaşıklığı varsayıyoruz.

Şimdi özetler bazı kimlik kuralları kullanarak basitleştirilmiş olabilir:

  1. Toplamı(1 N w)( C ) = N * C
  2. Toplamı(w 1-N)( A ( /-) B ) = Toplamı(w 1-N)( A ) ( /-) Toplam(w 1-N)( B )
  3. Toplamı(1 N w)( w * C ) = C * Toplamı(1 N w)( w ) (C w sürekli, bağımsız)
  4. Toplamı(1 N w)( w ) = (w * (g 1)) / 2

Bazı Cebir uygulanması

f(N) = Summation(i from 1 to N / 2)( (N - (i - 1) * 2) * ( C ) )   (N / 2)( C )

f(N) = C * Summation(i from 1 to N / 2)( (N - (i - 1) * 2))   (N / 2)( C )

f(N) = C * (Summation(i from 1 to N / 2)( N ) - Summation(i from 1 to N / 2)( (i - 1) * 2))   (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - 2 * Summation(i from 1 to N / 2)( i - 1 ))   (N / 2)( C )

=> Summation(i from 1 to N / 2)( i - 1 ) = Summation(i from 1 to N / 2 - 1)( i )

f(N) = C * (( N ^ 2 / 2 ) - 2 * Summation(i from 1 to N / 2 - 1)( i ))   (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - 2 * ( (N / 2 - 1) * (N / 2 - 1   1) / 2) )   (N / 2)( C )

=> (N / 2 - 1) * (N / 2 - 1   1) / 2 = 

   (N / 2 - 1) * (N / 2) / 2 = 

   ((N ^ 2 / 4) - (N / 2)) / 2 = 

   (N ^ 2 / 8) - (N / 4)

f(N) = C * (( N ^ 2 / 2 ) - 2 * ( (N ^ 2 / 8) - (N / 4) ))   (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - ( (N ^ 2 / 4) - (N / 2) ))   (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - (N ^ 2 / 4)   (N / 2))   (N / 2)( C )

f(N) = C * ( N ^ 2 / 4 )   C * (N / 2)   C * (N / 2)

f(N) = C * ( N ^ 2 / 4 )   2 * C * (N / 2)

f(N) = C * ( N ^ 2 / 4 )   C * N

f(N) = C * 1/4 * N ^ 2   C * N

Ve BigOh

O(N ^ 2)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • arnejann

    arnejann

    3 Kasım 2007
  • HuskyStarcraft

    HuskyStarcra

    4 HAZİRAN 2009
  • TheForgottenGamer1

    TheForgotten

    28 AĞUSTOS 2009