1 / 35

Сложност на алгоритми

Сложност на алгоритми. Кр. Манев, Бургас 09.2008. Задачи и алгоритми. З адача (в математически смисъл): „ Упражне-ние по математика, физика и др., което се разрешава чрез разсъждения и изчисления “ . (Тълковен речник на българския език).

elwyn
Download Presentation

Сложност на алгоритми

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Сложност на алгоритми Кр. Манев, Бургас 09.2008

  2. Задачи и алгоритми • Задача (в математически смисъл): „Упражне-ние по математика, физика и др., което се разрешава чрез разсъждения и изчисления“. (Тълковен речник на българския език). • Дьорд Пойя : „Да имаме задача означава да търсим съзнателно някое действие, годно за постигането на една ясно схващана, но не и непосредствено достижима цел. Да се реши една задача означава да се намери това действие.“

  3. Задачи и алгоритмиМасова задача • Дадено: МножествоX= {x1, x2, x3,…} от обекти с определени свойства (всяко xi може да приема множество стойности – параметър) и множествоD= {d1, d2, d3,…} от операции (действия). • Търси се: МножествоY= {y1, y2, y3,…} от обекти с определени свойства - резултат, което да се получи от X, с прилагане на операциите от D. • Решение: Не резултаът, а последователността от операции, с които сме го намерили

  4. Задачи и алгоритмиПримери замасови задачи • Дадени са естествените числа iиj.С прилагане на аритметични операции (вкл. сравняване) да се намери НОД на iиj. • Дадени са естествените числа i, jиk>0.С при-лагане на аритметични операции (вкл. сравня-ване) да се провери дали k е НОД на iиj. са масови задачи. • Да се намери НОД на 12 и 30. • Да се провери дали 6 е НОД на 12 и 30. са екземпляри на тези масови задачи – получени са с фиксиране на някои/всички параметри.

  5. Задачи и алгоритмиРешение намасова задача (МЗ) • Решение на МЗще наричаме строго определена крайна последователност от стъпки (процедура), която започвайки от зададените стойности на параметрите на произволен екземпляр на МЗ и прилагайки на всяка стъпка някоя от допустимите операции, намира резултата за този екземпляр на масовата задача - АЛГОРИТЪМ

  6. Задачи и алгоритмиРазрешими и неразрешими МЗ • Не за всяка МЗ съществува алгоритъм, който да намира резултат за всеки екземпляр на задачата – неразрешима МЗ. • Разрешимите МЗ също не са безпроблем-ни – много често, първият попаднал ни алгоритъм за рещаване на МЗ е неудов-летворителен.

  7. Сложност на задачи и алгоритми • Много е важно за тази теория, да сe различават понятията сложност на алгоритъм и сложност на задача. • Обикновено, същствуват много алгоритми за решаване на МЗ и всички те могат да имат различна сложност. • Сложност на МЗ бихме могли да нарчем сложността на най-добрия алгоритъм който я решава. Ако знаехме кой е той!!!

  8. Сложност на алгоритми • За да можем да дефинираме понятието сложност на алгоритъм ще трябва да направим важни стъпки: • Да фиксираме множеството от възможни стойности на параметрите на МЗ. • Да фиксираме изчислителния формализъм – операции, начин на представяне на процедурите (синтаксис и семантика). • Да определим изключително важното за теорията понятие размер на входа.

  9. Сложност на алгоритмиСтойности на параметрите • Ще фиксираме като множеството от възможни стойности на параметрите на МЗ стойности от множеството на целите числа. • Компютърът релно работи с подмоножество на целите числа, но то с годините се разширява – 8b, 16b, 32b, 64b, 128b... • Дробните числа в компютъра се моделират с двойка цели – мантиса и порядък. Представя-нето е неравномерно, аритметиката проблем-на: може да се случи (a*b)*c  a* (b*c)

  10. Сложност на алгоритмиИзчислителен формализъм • Машината с произволен достъп до паметта (МПД) е упростен модел на съвременния компютър • Всяка клетка на ВЛ, ИЛ и паметта с произволен достъп, както и Акумула-торът (AC) съдържат r-разряд-но цяло - r-разрядна МПД.

  11. Сложност на алгоритмиИзчислителен формализъм • Програмната памет е със-тавена от клетки. Всяка клетка има свой адрес и може да съдържа по една команда. • Клетката PC (брояч на ко-мандите) съдържа адреса на текущо изпълняваната команда - r-разрядно положително цяло.

  12. Сложност на алгоритмиИзчислителен формализъм • Всяка команда е съставена от КОД + АРГУМЕНТ (r-разряда) • Използват се 3 типа команди • Непосредствен операнд: CODE# Z– операцията се извъшва с числото Z • Спряк адрес: CODE A – операцията се извъшва с числотонамиращо се в клетка с адрес A - <A> • Скосвен адрес: CODE& A– операцията се извъшва с числотонамиращо се в клетка с адрес, който се намира в клетката с адрес A - <<A>>.

  13. Сложност на алгоритмиИзчислителен формализъм • Да разгледаме за пример командите за събиране • Непосредствен операнд: ADD# 100– към съдържанието на АC се добавя 100. Означаваме <AC>:=<AC>+100 • Спряк адрес: ADD 100– към съдържанието на АC се добавя съдържанието на клетката с адрес 100 -<AC>:=<AC>+<100> • Скосвен адрес: ADD& 100– към съдържани-ето на АC се добавя съдържанието на клет-ката с адрес, който се намира в клетката с адрес 100 - <AC>:=<AC>+<<100>>. • При всяка от тези команди <PC>:=<PC>+1

  14. Сложност на алгоритмиИзчислителен формализъм • Подобни са всички останали команди на МПД от „аритметичен“ тип: • Изваждане SUB# Z, SUB A, SUB& A • Умножение MUL# Z, MUL A, MUL& A • Деление DIV# Z, DIV A, DIV & A • Остатък при деление MOD# Z, MOD A, MOD & A • Побитова дизюнкция OR# Z, OR A, OR & A • Побитова конюнкция AND# Z, AND A, AND & A • Изместване наляво SHL# Z, SHL A, SHL & A • Изместване надясно SHR# Z, SHR A, SHR & A • и.т.н.

  15. Сложност на алгоритмиИзчислителен формализъм • Команди за работа с Акумулатора: • LOAD# Z - <AC>:=Z, <PC>:=<PC>+1 • LOAD A - <AC>:=<A>, <PC>:=<PC>+1 • LOAD & A - <AC>:=<<A>>, <PC>:=<PC>+1 • STORE A - <A>:=<AC>, <PC>:=<PC>+1 • STORE& A - <<A>>:=<AC>, <PC>:=<PC>+1 • Команди за вход и изход • INPUT - <AC>:=<поредна клетка на ВЛ> <PC>:=<PC>+1 • OUTPUT – <поредна клетка на ИЛ>:=<AC> <PC>:=<PC>+1

  16. Сложност на алгоритмиИзчислителен формализъм • Команди за преходи: • JMP B - <PC>:= B • JMPZ B – ако <AC> = 0, <PC>:=B, иначе <PC>:=<PC>+1 • JMPP B – ако <AC> > 0, <PC>:=B, иначе <PC>:=<PC>+1 • JMPN B – ако <AC> < 0, <PC>:=B, иначе <PC>:=<PC>+1 • Команда за прекратяване на работата: • STOP

  17. Сложност на алгоритмиИзчислителен формализъм • Задача: да се състави програма за МПД, която въвежда от ВЛ положителни числа до срещане на 0 и запомня в паметта тези числа (нещо като масив) и броя им. • Първата работа при съставяне на програма за МПД е да си разпределим паметта: • В клетката с адрес 0 ще си организираме индекс на масива от числа, а като завършим четенето от него ще намерим и броя на числата • В клетката с адрес 1 ще поставим първото въведено число, в клетката с адрес 2 – второто, в клетката с адрес 3 –третото и т.н.

  18. Сложност на алгоритмиИзчислителен формализъм 0) LOAD# 1// поставяме 1 в АС 1) STORE 0 // съхраняваме 1 в клетка 0 (индекс) 2) INPUT // въвеждаме поредно число в АС 3) JMPZ 9 // ако е въведена 0 - команда 9) 4) STORE& 0 // записваме числото в адреса от клетка 0 5) LOAD 0 // стойността на индекса - в АС 6) ADD# 1 // увеличаваме индекса с 1 7) STORE 0 // нова стойност на индекса в клетка 0 8) JMP 2 // връщаме се за ново четене 9) LOAD 0 // стойността на индекса в АС 10) SUB# 1 // намаляваме индекса с 1 11) STORE 0 // бройна числата в клетка 0 12) OUTPUT // извеждаме резултата 13) STOP // прекратяваме изпълнението

  19. Сложност на алгоритмиРазмер на входа • Последната стъпка, която трябва да направим, преди да дефинираме сложност на алгоритъм, е да кажем как ще определяме размер на входа. • Определянето на размер на входа е много сложна задача, затова ще отложим засега окончателното определяне на тази стъпка. • За сега ще считаме, че размерът на входа е приблизително равен на броя на прочетените от ВЛ числа. За нашия пример нека да вземем за размер на входа броя N на положителните числа, които четем от лентата. Това, че изключваме прочетената 0 от рзмера на входа е несъществено.

  20. Сложност на алгоритмиСложност по време • Сложност по време на един алгоритъм A ще наричаме сложността на програмата за МПД, с която е реализиран.Да означим с #броя на командите, изпълнени от МПД при работата й върху вход .Дефинираме два вида сложност по време на програми за МПД: • сложност по време в най-лошия случай: tA(N) = max с размер N{#} • сложност по време в средния случай: tA*(N) =  с размер N{#}/ |{с размер N}| • По различни причини ще се занимаваме само със сложността в най-лошия случай.

  21. Сложност на алгоритмиСложност по памет • Сложност по памет на един алгоритъм A ще наричаме сложността на програмата за МПД, с която е реализиран.Да означим с @броя на клетките памет, използвани от МПД при работата й върху вход .Дефинираме два вида сложност по памет на програми за МПД: • сложност по памет в най-лошия случай: sA(N) = max с размер N{@} • сложност по памет в средния случай: sA*(N) =  с размер N{@}/ |{с размер N}| • По различни причини няма да се занимаваме сега със сложността по памет.

  22. Сложност на алгоритмиСложност по време 0) LOAD# 1// 1 път 1) STORE 0 // 1 път 2) INPUT // N+1 пъти 3) JMPZ 9 // N+1 пъти 4) STORE& 0 // N пъти 5) LOAD 0 // N пъти 6) ADD# 1 // N пъти 7) STORE 0 // N пъти 8) JMP 2 // N пъти 9) LOAD 0 // 1 път 10) SUB# 1 // 1 път 11) STORE 0 // 1 път 12) OUTPUT // 1 път 13) STOP // 1 път

  23. Сложност на алгоритмиСложност за примера • И така, за нашия пример получаваме: • за сложносттта по време в най-лошия случай: tA(N) = 7.N + 9 • за сложността по време в средния случай, тъй като всички случаи са еднакви: tA*(N) = tA(N) = 7.N + 9 • за сложносттта по памет и в най-лошия случайи в средния случай, тъй като всички случаи са еднакви: sA*(N) = sA(N) = N + 1

  24. Сложност на алгоритмиПрограма на С • В състезателната дейност не използваме МПД и затова ще се наложи да пренесем представе-ната теория в друг изчислителен формализъм – език за програмиане. • По понятни причини ще използаме езика С, но пренасянето на теорията няма да се различава съществено, ако използаваме друг език за програмиране. • Основен принцип при пренасянето ще бъде следният: ще се опитаме да съпоставим на програмата на С такава сложност, каквато бихме получили, ако програмата беше написана на езика на МПД.

  25. Сложност на алгоритмиПрограма на С • Сложност tе(N) на израз е в програма на С, както и сложността на съответния оператор е; ще дефинираме като броя на всички знаци на операции в израза, плюс броя на всички скоби (както “кръгли”, така и индексни), влючително и тези пропуснати заради приоритети. • Пример: (m[i+1])=(a+(b*C))- сложност 12 а всъщност е 10, но това е удовлетворително LOAD iMUL c ADD# 1STORE d ADD mLOAD a STORE tADD d LOAD bSTORE& t

  26. Сложност на алгоритмиПрограма на С • Сложността на блока от оператори {oper 1;oper 2;…;oper K; } в програма на Сще дефинираме като tblck(N) = toper 1(N) + toper 2(N) + … + toper K(N). • Сложността на условния оператор if expr oper в програма на Сще дефинираме като tif(N) = texpr(N) + toper (N). • Сложността на условния оператор if expr oper 1 else oper 2 в програма на Сще дефинираме като tif_else(N) = texpr(N) + max {toper 1(N), toper 2(N)}

  27. Сложност на алгоритмиПрограма на С • За да определим сложността на оператора за цикъл while expr oper първо определяме броя c(N) наитерациите. • Ако сложността toper не зависи от N, тогава twhile(N) = (c(N)+1)texpr(N) + c(N)toper. • Ако сложността toper зависи от N, да означим с ti(N) сложносттана i-тата итерация. Тогава twhile(N) = (c(N)+1)texpr(N) + t1(N) + t2(N)+…+ tc(N)(N) • За цикъла do operwhile expr постъпваме аналогично

  28. Сложност на алгоритмиПрограма на С • За пример нека да определим сложността на алгоритъма “на мехурчето” за сортиране на Nчисла. За размер на входа да приемем N. int a[],N; bubble_sort() { int i,j,t; for(i=N-1;i>0;i--) for(j=1;j<=i;j++) if(a[j]>a[j+1]) {t=a[j];a[j]=a[j+1];a[j+1]=t;} }

  29. Сложност на алгоритмиПрограма на С int a[],N,; bubble_sort() { int i,j,t; 3 2 3 for(i=N-1;i>0;i--) 3+N*5+i=1,…,N-1f(i) 2 3 3 for(j=1;j<=i;j++)2+(i+1)*6+i*30= 10 =36*i+8=f(i) 30 if(a[j]>a[j+1]) 59 6 20{t=a[j];a[j]=a[j+1];a[j+1]=t;} }

  30. Сложност на алгоритмиПрограма на С И така за сложността на алгоритъма на мехурчето получаваме: tbubble_sort(N)= 3 +5N + i=1,2,…,N-1 f(i) = = 3 +5N + i=1,2,…,N-1 (36i + 8) = = 3 +5N+8(N – 1) +36 i=1,2,…,N-1 i = = 13N – 5 + 18N(N – 1) = = 18N2– 5N – 5

  31. Сложност на алгоритмиИзвикване на програми • За да определим сложността на оператор, в който има извикване на функция f, трябва • да разгледаме съответната функция f като имплементация на специфичен алгоритъм; • да определим за този алгоритъм какво е размер N* на входаи да пресметнем сложността tf(N*); • Да се върнем в оператора и да изразим N* като функция на N: N* = g(N). • Тогава сложността на извикването ще бъде tf(g(N))

  32. Сложност на алгоритмиИзвикване на програми • За пример нека да разгледаме версия на алгоритъма “на мехурчето” за сортиране на първите N* измежду зададени Nчисла. int a[],N; bubble_sort(int N*) { int i,j,t; for(i=N*-1;i>0;i--) for(j=1;j<=i;j++) if(a[j]>a[j+1]) {t=a[j];a[j]=a[j+1];a[j+1]=t;} } Сложността му е tbubble_sort(N*) = 18.(N*)2 – 15N* – 5

  33. Сложност на алгоритмиИзвикване на програми • Да рагледаме следния алгоритъм. • int a[],N,; alabala() { int i; for(i=1;i<=N;i++) bubble_sort(int i)} Сложността му ще бъде talabala(N) = 2 + (N + 1).6 + i=1,2,…,N tbubble_sort(i) = = 6N + 8 + i=1,2,…,N (18.i2– 15i – 5) = = 6N + 8 + 3N(N + 1)(2N + 1) –7.5N(N + 1) – 5N= = 6N +8 + 6N3 + 9N2+ 3N – 7.5N 2 – 7.5N – 5N= =6N3 +1.5 N2 – 3.5N + 8

  34. Сложност на алгоритмиРекурсивни извиквания • Да рагледаме следния алгоритъмза сортиране на масив, съдържащ рекурсивни извиквания: int a[],N; int main(){merge_sort(1,N);return 0;} merge_sort(int i,int j) { int k; if(i==j) return; k=(i+j)/2;merge_sort(i,k); merge_sort(k+1,j); merge(i,k,j);} Сложността му е: t(N)=t merge_sort(N)=3+4+2tmerge_sort (N)+tmerge (N),N > 1 t(1)= const - рекурентно отношение

  35. Сложност на алгоритмиРекурсивни извиквания • Да рагледаме популярния алгоритъмза търсене на число в сортиран масив, съдържащ рекурсивно извикване: int a[],N,x; int main(){bin_search(1,N);return 0;} bin_search(int i,int j) { while(i<=j) {int k=(i+j)/2; if(x==a[k]) return k; if(x<a[k])bin_search(i,k-1); else bin_search(k+1,j);}} Сложността му се изразява с рекурентното отношение: t(1)= const t(N)=t bin_search(N)=3+4+6+6+tbin_search(N/2), N > 1

More Related