├── README.md ├── chapter01 ├── base.c ├── bell.c ├── cnk.c ├── codeperm.c ├── comb.c ├── devnum.c ├── devnum2.c ├── devnum3.c ├── digits.c ├── digitsnf.c ├── fact.c ├── factrec.c ├── factzero.c ├── fibiter.c ├── fibrec.c ├── gcditer.c ├── gcdrec.c ├── lcm.c ├── matrix.c ├── mult.c ├── multmat.c ├── numdev.c ├── pascalt.c ├── perfect.c ├── permswap.c ├── permute.c ├── power.c ├── preproc.c ├── prime.c ├── print.c ├── print1.c ├── print2.c ├── print3.c ├── printrec.c ├── rom2dec.c ├── runproc.c ├── sieve.c ├── sum1.c ├── sum2.c ├── summat.c ├── sumzero.c └── variate.c ├── chapter02 ├── bintree.c ├── bintree2.c ├── hash.c ├── hashset.c ├── list.c ├── queue.c ├── stack1.c └── stack2.c ├── chapter03 ├── bitsort.c ├── bitsort2.c ├── bubsort1.c ├── bubsort2.c ├── combsort.c ├── count_s.c ├── count_s2.c ├── heapsort.c ├── insert_b.c ├── insert_s.c ├── inserts2.c ├── permsort.c ├── qsort.c ├── radsort.c ├── selsort.c ├── selsort2.c ├── set_sort.c ├── setsort2.c ├── shaker.c ├── shell.c └── shell2.c ├── chapter04 ├── binsear0.c ├── binsear1.c ├── binsear2.c ├── binsear3.c ├── binsear4.c ├── fibsear.c ├── interpol.c ├── jumpsear.c ├── reorder.c └── seq_arr.c ├── chapter05 ├── a-center.c ├── allcyc.c ├── artic.c ├── belman.c ├── bfs.c ├── bfsminw.c ├── btdfs.c ├── company.c ├── dfs.c ├── dijkstra.c ├── euler.c ├── floyd.c ├── fordfulk.c ├── formcycl.c ├── kruskal.c ├── longpath.c ├── maxindep.c ├── mindom.c ├── p-center.c ├── prim.c ├── strcon1.c ├── strconn.c ├── topsort.c ├── topsortf.c ├── trans-or.c ├── tsp.c └── v-base.c ├── chapter06 ├── bagrec.c ├── bool.c ├── boolcut.c ├── colorm2.c ├── knight.c ├── longpath.c ├── program.c ├── queens.c ├── tictac.c └── translat.c ├── chapter07 ├── binmerge.c ├── hanoy.c ├── heap.c ├── major1.c ├── major10.c ├── major11.c ├── major12.c ├── major13.c ├── major2.c ├── major3.c ├── major6.c ├── major7.c ├── major8.c ├── major9.c ├── maximum.c ├── merge_a.c ├── merge_l1.c ├── merge_l2.c ├── merge_l3.c ├── mergearr.c ├── mid_el2.c ├── mid_elem.c ├── powrec.c ├── shift1.c ├── shift2.c ├── shift3.c ├── tourn1.c ├── tourn2.c └── tourn3.c ├── chapter08 ├── alanbob.c ├── alanbob2.c ├── binom.c ├── binom2.c ├── board.c ├── breaknum.c ├── catalan.c ├── cfl.c ├── coin_min.c ├── coinmin2.c ├── coins.c ├── cuts.c ├── domino.c ├── fibmatr.c ├── fibmemo.c ├── fibmemo2.c ├── fibrec.c ├── hedonia.c ├── knapsack1.c ├── knapsack2a.c ├── knapsack2b.c ├── knapsack3a.c ├── knapsack3b.c ├── knapsack3c.c ├── knapsack4.c ├── knapsack5.c ├── lcs1.c ├── lcs2.c ├── lns1.c ├── lns2.c ├── lns3.c ├── matrix1.c ├── matrix2.c ├── matrix3.c ├── no2zero.c ├── partitio.c ├── railway.c ├── relation.c ├── resource.c ├── ring.c ├── room.c ├── saw.c ├── series.c ├── series2.c ├── series3.c ├── series4.c ├── taxi.c ├── tickets.c ├── transform.c ├── tree.c ├── trees.c └── triangle.c ├── chapter09 ├── aselect.c ├── colorg.c ├── egypt.c ├── fracknap.c ├── hamgray.c ├── knightg.c ├── pi.c ├── prime_mc.c ├── schedule.c └── tspgenet.c └── chapter10 ├── arithmet.c ├── entropy.c ├── huffman1.c ├── huffman2.c ├── huffman3.c ├── lpc.c └── lzw.c /README.md: -------------------------------------------------------------------------------- 1 | # Programming += Algorithms Book - Original C Sources 2 | 3 | ![Programming += Algorithms Book](http://www.programirane.org/wp-content/uploads/2015/12/ProgramiraneAlgoritmi-Korica-Peto-Izdanie.png "Programming += Algorithms;") 4 | 5 | 6 | 7 | Book Authors: 8 | * Preslav Nakov 9 | * Panayot Dobrikov 10 | 11 | Official site: 12 | [http://www.programirane.org/](http://www.programirane.org/) 13 | -------------------------------------------------------------------------------- /chapter01/bell.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | const unsigned long n = 10; 6 | 7 | unsigned long M[MAXN+1]; 8 | void stirling(unsigned n) 9 | { unsigned i, j; 10 | if (n == 0) M[0] = 1; 11 | else M[0] = 0; 12 | for (i = 1; i <= n; i++) { 13 | M[i] = 1; 14 | for (j = i - 1; j >= 1; j--) M[j] = j * M[j] + M[j - 1]; 15 | } 16 | } 17 | 18 | unsigned long bell(unsigned n) 19 | { unsigned i; 20 | unsigned long result = 0; 21 | for (i = 0; i <= n; i++) result += M[i]; 22 | return result; 23 | } 24 | 25 | int main(void) { 26 | stirling(n); 27 | printf("bell(%lu)= %lu\n", n, bell(n)); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /chapter01/cnk.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 500 4 | 5 | unsigned long n = 7; 6 | unsigned long k = 3; 7 | 8 | unsigned long pN, primes[MAXN], counts[MAXN]; 9 | 10 | void modify(long int x, int how) 11 | { unsigned i; 12 | for (i = 0; i < pN; i++) 13 | if (x == primes[i]) { counts[i] += how; return; } 14 | counts[pN] = how; 15 | primes[pN++] = x; 16 | } 17 | 18 | void solve(unsigned long start, unsigned long end, unsigned long inc) 19 | { unsigned long prime, mul, how, i, max; 20 | for (i = start; i <= end; i++) { 21 | mul = i; 22 | prime = 2; 23 | while (mul != 1) { 24 | for (how = 0; mul % prime == 0; mul /= prime, how++); 25 | if (how > 0) modify(prime, inc * how); 26 | prime++; 27 | } 28 | } 29 | } 30 | 31 | long int calc(void) 32 | { int i, j; 33 | long int result = 1; 34 | for (i = 0; i < pN; i++) 35 | for (j = 0; j < counts[i]; j++) result *= primes[i]; 36 | return result; 37 | } 38 | 39 | int main(void) { 40 | printf("C(%lu,%lu)= ", n, k); 41 | pN = 0; 42 | if (n - k < k) k = n - k; 43 | solve(n - k + 1, n, 1); /* Факторизира числителя (n–k+1),...,n */ 44 | solve(1, k, -1); /* Факторизира знаменателя 1,...,k */ 45 | printf("%lu\n", calc()); 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /chapter01/codeperm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | const unsigned n = 6; 6 | const unsigned perm[MAXN] = { 5, 3, 6, 4, 2, 1 }; 7 | const unsigned long code = 551; 8 | 9 | unsigned long codePerm(unsigned n, unsigned perm[]) 10 | { unsigned p[MAXN], i, pos; 11 | unsigned long r, result; 12 | result = 0; 13 | for (i = 0; i < n; i++) p[i] = i + 1; 14 | for (pos = 0; pos < n; pos++) { 15 | r = 0; 16 | while (perm[pos] != p[r]) r++; 17 | result = result * (n - pos) + r; 18 | for (i = r + 1; i < n; i++) p[i - 1] = p[i]; 19 | } 20 | return result; 21 | } 22 | 23 | void decodePerm(unsigned long num, unsigned n, unsigned perm[]) 24 | { unsigned long r, m, k; 25 | unsigned i, p[MAXN]; 26 | for (i = 0; i < n; i++) p[i] = i + 1; 27 | k = n; 28 | do { 29 | m = n - k + 1; 30 | perm[k - 1] = num % m; 31 | if (k > 1) num /= m; 32 | } while (--k > 0); 33 | k = 0; 34 | do { 35 | m = perm[k]; perm[k] = p[m]; 36 | if (k < n) 37 | for (i = m + 1; i < n; i++) p[i - 1] = p[i]; 38 | } while (++k < n); 39 | } 40 | 41 | int main(void) { 42 | unsigned i; 43 | printf("Дадената пермутация се кодира като %lu \n", codePerm(n, perm)); 44 | printf("Декодираме пермутацията отговаряща на числото %lu: ", code); 45 | decodePerm(code, n, perm); 46 | for (i = 0; i < n; i++) printf("%u ", perm[i]); 47 | printf("\n"); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /chapter01/comb.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* comment */ 4 | #define MAXN 20 5 | 6 | /* Намира всички комбинации на n елемента от k-ти клас */ 7 | const unsigned n = 5; 8 | const unsigned k = 3; 9 | 10 | unsigned mp[MAXN]; 11 | 12 | void print(unsigned length) 13 | { unsigned i; 14 | for (i = 0; i < length; i++) printf("%u ", mp[i]); 15 | printf("\n"); 16 | } 17 | 18 | void komb(unsigned i, unsigned after) 19 | { unsigned j; 20 | if (i > k) return; 21 | for (j = after + 1; j <= n; j++) { 22 | mp[i - 1] = j; 23 | if (i == k) print(i); 24 | komb(i + 1, j); 25 | } 26 | } 27 | 28 | int main(void) { 29 | printf("C(%u,%u): \n", n, k); 30 | komb(1, 0); 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /chapter01/devnum.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | const unsigned n = 7; 6 | 7 | unsigned mp[MAXN + 1]; 8 | 9 | void print(unsigned length) 10 | { unsigned i; 11 | for (i = 1; i < length; i++) printf("%u+", mp[i]); 12 | printf("%u\n", mp[length]); 13 | } 14 | 15 | void devNum(unsigned n, unsigned pos) 16 | { unsigned k; 17 | for (k = n; k >= 1; k--) { 18 | if (n != k) { 19 | mp[pos] = k; 20 | if (mp[pos] <= mp[pos - 1]) { 21 | devNum(n - k, pos + 1); 22 | } 23 | } 24 | else { 25 | mp[pos] = k; 26 | if (mp[pos] <= mp[pos - 1]) print(pos); 27 | } 28 | } 29 | } 30 | 31 | int main(void) { 32 | mp[0] = n+1; 33 | devNum(n, 1); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /chapter01/devnum2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой на множителите, най-много log2n (минималният е 2). */ 4 | #define MAXLN 20 5 | 6 | /* Число, което ще разбираме */ 7 | const unsigned n = 50; 8 | 9 | unsigned mp[MAXLN]; 10 | 11 | void print(unsigned length) 12 | { unsigned i; 13 | for (i = 1; i < length; i++) printf("%u * ", mp[i]); 14 | printf("%d\n", mp[length]); 15 | } 16 | 17 | void devNum(unsigned n, unsigned pos) 18 | { unsigned k; 19 | for (k = n; k > 1; k--) { 20 | if (n != k) { 21 | mp[pos] = k; 22 | if (mp[pos] <= mp[pos - 1]) 23 | if (n % k == 0) devNum(n / k, pos + 1); 24 | } 25 | else { 26 | mp[pos] = k; 27 | if (mp[pos] <= mp[pos - 1]) print(pos); 28 | } 29 | } 30 | } 31 | 32 | int main(void) { 33 | mp[0] = n + 1; 34 | devNum(n, 1); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /chapter01/devnum3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX_ADDS 100 4 | 5 | /* Сума, която ще разбиваме */ 6 | const unsigned n = 15; 7 | /* Брой различни стойности на монетите */ 8 | const unsigned gN = 3; 9 | /* Стойности на монетите */ 10 | const unsigned given[] = { 2, 3, 5 }; 11 | 12 | unsigned mp[MAX_ADDS]; 13 | 14 | void print(unsigned lenght) 15 | { unsigned i; 16 | for (i = 1; i < lenght; i++) printf("%u + ", mp[i]); 17 | printf("%d\n", mp[lenght]); 18 | } 19 | 20 | void devNum(unsigned n, unsigned pos) 21 | { unsigned k, p; 22 | for (p = gN; p > 0; p--) { 23 | k = given[p - 1]; 24 | if (n > k) { 25 | mp[pos] = k; 26 | if (mp[pos] <= mp[pos - 1]) devNum(n - k, pos + 1); 27 | } 28 | else if (n == k) { 29 | mp[pos] = k; 30 | if (mp[pos] <= mp[pos - 1]) print(pos); 31 | } 32 | } 33 | } 34 | 35 | int main(void) { 36 | mp[0] = n + 1; 37 | devNum(n, 1); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /chapter01/digits.c: -------------------------------------------------------------------------------- 1 | unsigned n = 4242; 2 | 3 | int main(void) { 4 | unsigned digits; 5 | for (digits = 0; n > 0; n /= 10, digits++); 6 | printf("Броят на цифрите на %u е %u\n", n, digits); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /chapter01/digitsnf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const unsigned long n = 123; 5 | 6 | int main(void) 7 | { float digits = 0; 8 | unsigned i; 9 | for (i = 1; i <= n; i++) { 10 | digits += log10(i); 11 | } 12 | 13 | /* операцията [x] ще реализираме, като използваме превръщане до тип unsigned long */ 14 | printf("Броят на цифрите на %lu! е %lu\n", n, (unsigned long) digits + 1); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /chapter01/fact.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned n = 10; 4 | 5 | unsigned long factoriel(unsigned n) 6 | { unsigned i; 7 | unsigned long r = 1; 8 | for (i = 2; i <= n; i++) r *= i; 9 | return r; 10 | } 11 | 12 | int main() { 13 | printf("%u! = %lu\n", n, factoriel(n)); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /chapter01/factrec.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned n = 6; 4 | 5 | unsigned i; 6 | unsigned long fact(void) 7 | { if (i == 1) return 1; 8 | return --i * fact(); 9 | } 10 | 11 | int main(void) { 12 | i = n + 1; 13 | printf("%u! = %lu \n", n, fact()); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /chapter01/factzero.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned n = 10; 4 | 5 | int main(void) { 6 | unsigned zeroes = 0, p = 5; 7 | while (n >= p) { 8 | zeroes += n / p; 9 | p *= 5; 10 | } 11 | printf("Броят на нулите в края на %u! е %u\n", n, zeroes); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /chapter01/fibiter.c: -------------------------------------------------------------------------------- 1 | //n->const, FibIter -> fibIter 2 | #include 3 | 4 | const unsigned n = 7; 5 | 6 | unsigned long fibIter(unsigned n) 7 | { unsigned long f1 = 0, f2 = 1; 8 | unsigned i = 0; 9 | while (i < n) { 10 | f2 = f1 + f2; 11 | f1 = f2 - f1; 12 | i++; 13 | } 14 | return f2; 15 | } 16 | 17 | int main() { 18 | printf("fib(%u) = %lu\n", n, fibIter(n)); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /chapter01/fibrec.c: -------------------------------------------------------------------------------- 1 | // da oprawq w teksta 2 | // fib(7) dawaha razlichno - da checkna koe e po definiciqta!!! 3 | #include 4 | 5 | const unsigned n = 7; 6 | 7 | unsigned long fib(unsigned n) 8 | { if (n < 2) return 1; 9 | else return fib(n - 1) + fib(n - 2); 10 | } 11 | 12 | int main() { 13 | printf("fib(%u) = %lu\n", n, fib(n)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /chapter01/gcditer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned a = 28; 4 | const unsigned b = 49; 5 | 6 | unsigned gcd(unsigned a, unsigned b) 7 | { unsigned swap; 8 | while (b > 0) { 9 | swap = b; 10 | b = a % b; 11 | a = swap; 12 | } 13 | return a; 14 | } 15 | 16 | int main(void) { 17 | printf("NOD(%u,%u) = %u\n", a, b, gcd(a, b)); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /chapter01/gcdrec.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned a = 28; 4 | const unsigned b = 49; 5 | 6 | unsigned gcd(unsigned a, unsigned b) 7 | { return (b == 0) ? a : gcd(b, a % b); 8 | } 9 | 10 | int main(void) { 11 | printf("NOD(%u,%u) = %u\n", a, b, gcd(a, b)); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /chapter01/lcm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned n = 4; 4 | unsigned A[] = { 10, 8, 5, 9 }; 5 | 6 | unsigned gcd(unsigned a, unsigned b) 7 | { return (b == 0) ? a : gcd(b, a % b); 8 | } 9 | 10 | unsigned lcm(unsigned a[], unsigned n) 11 | { unsigned b; 12 | if (n == 2) 13 | return(a[0] * a[1]) / (gcd(a[0], a[1])); 14 | else { 15 | b = lcm(a, n - 1); 16 | return(a[n - 1] * b) / (gcd(a[n - 1], b)); 17 | } 18 | } 19 | 20 | int main(void) 21 | { printf("%u\n", lcm(A, n)); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /chapter01/matrix.c: -------------------------------------------------------------------------------- 1 | /* Въвеждане по редове */ 2 | for (i = 0; i < m; i++) 3 | for (j = 0; j < n; j++) scanf("%d", &A[i][j]); 4 | 5 | /* Въвеждане по стълбове */ 6 | for (i = 0; i < m; i++) 7 | for (j = 0; j < n; j++) scanf("%d", &A[j][i]); 8 | 9 | /* Отпечатване на матрица по редове */ 10 | for (i = 0; i < m; i++) { 11 | for (j = 0; j < n; j++) printf("%.3d", A[i][j]); 12 | printf("\n"); 13 | } 14 | -------------------------------------------------------------------------------- /chapter01/mult.c: -------------------------------------------------------------------------------- 1 | int a[n]; 2 | int mult(void) 3 | { unsigned int i; 4 | int s = 1; 5 | for (i = 0; i < n; i++) s *= a[i]; 6 | return s; 7 | } 8 | -------------------------------------------------------------------------------- /chapter01/multmat.c: -------------------------------------------------------------------------------- 1 | for (i = 0; i < m; i++) 2 | for (j = 0; j < p; j++) { 3 | C[i][j] = 0; 4 | for (k = 0; k < n; k++) C[i][j] += A[i][k] * B[k][j]; 5 | } 6 | -------------------------------------------------------------------------------- /chapter01/numdev.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Число, което ще се разлага */ 4 | unsigned n = 435; 5 | 6 | int main(void) { 7 | unsigned how, i, j; 8 | 9 | printf("%u = ", n); 10 | i = 1; 11 | while (n != 1) { 12 | i++; 13 | how = 0; 14 | while ((n % i) == 0) { 15 | how++; 16 | n = n / i; 17 | } 18 | for (j = 0; j < how; j++) printf("%u ", i); 19 | } 20 | printf("\n"); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /chapter01/pascalt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален размер на триъгълника */ 4 | #define MAXN 1000 5 | 6 | unsigned n = 7; 7 | unsigned k = 3; 8 | 9 | unsigned long lastLine[MAXN + 1]; 10 | 11 | int main(void) { 12 | unsigned i, j; 13 | lastLine[0] = 1; 14 | for (i = 1; i <= n; i++) { 15 | lastLine[i] = 1; 16 | for (j = i - 1; j >= 1; j--) 17 | lastLine[j] += lastLine[j - 1]; 18 | } 19 | printf("C(%u,%u) = %lu\n", n, k, lastLine[k]); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /chapter01/perfect.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MN 10 4 | 5 | unsigned mPrimes[MN] = { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89 }; 6 | unsigned k, number[200]; 7 | 8 | void doubleN(void) 9 | { unsigned i, carry = 0, temp; 10 | for (i = 0; i < k; i++) { 11 | temp = number[i] * 2 + carry; 12 | number[i] = temp % 10; 13 | carry = temp / 10; 14 | } 15 | if (carry > 0) number[k++] = carry; 16 | } 17 | 18 | void print(void) 19 | { unsigned i; 20 | for (i = k; i > 0; i--) printf("%u", number[i-1]); 21 | printf("\n"); 22 | } 23 | 24 | void perfect(unsigned s, unsigned m) 25 | { unsigned i; 26 | k = 1; number[0] = 1; 27 | for (i = 0; i < m; i++) doubleN(); /* това са делители от вида 2^i */ 28 | number[0]--; /* последната цифра със сигурност е измежду {2,4,8,6} */ 29 | for (i = 0; i < m - 1; i++) doubleN(); 30 | printf("%2u-т съвършено число е = ", s); 31 | print(); /* отпечатва поредното число */ 32 | } 33 | 34 | int main() { 35 | unsigned i; 36 | for (i = 1; i <= MN; i++) perfect(i, mPrimes[i - 1]); 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /chapter01/permswap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | const unsigned n = 3; 6 | 7 | unsigned a[MAXN]; 8 | 9 | void print(void) 10 | { unsigned i; 11 | for (i = 0; i < n; i++) printf("%u ", a[i] + 1); 12 | printf("\n"); 13 | } 14 | 15 | void permut(unsigned k) 16 | { unsigned i, swap; 17 | if (k == 0) print(); 18 | else { 19 | permut(k - 1); 20 | for (i = 0; i < k - 1; i++) { 21 | swap = a[i]; a[i] = a[k-1]; a[k-1] = swap; 22 | permut(k - 1); 23 | swap = a[i]; a[i] = a[k-1]; a[k-1] = swap; 24 | } 25 | } 26 | } 27 | 28 | int main(void) { 29 | unsigned i; 30 | printf("\n\n"); 31 | for (i = 0; i < n; i++) a[i] = i; 32 | permut(n); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /chapter01/permute.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | const unsigned n = 3; 6 | 7 | char used[MAXN]; 8 | unsigned mp[MAXN]; 9 | 10 | void print(void) 11 | { unsigned i; 12 | for (i = 0; i < n; i++) printf("%u ", mp[i] + 1); 13 | printf("\n"); 14 | } 15 | 16 | void permute(unsigned i) 17 | { unsigned k; 18 | if (i >= n) { print(); return; } 19 | for (k = 0; k < n; k++) { 20 | if (!used[k]) { 21 | used[k] = 1; 22 | mp[i] = k; 23 | permute(i+1); /* if (ако има смисъл да продължава генерирането) {permute(i+1);} */ 24 | used[k] = 0; 25 | } 26 | } 27 | } 28 | 29 | int main(void) { 30 | unsigned i; 31 | for (i = 0; i < n; i++) used[i] = 0; 32 | permute(0); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /chapter01/power.c: -------------------------------------------------------------------------------- 1 | float power(float x, unsigned y) 2 | { float res = x; 3 | unsigned i; 4 | for (i = 1; i < y; i++) res *= x; 5 | return res; 6 | } 7 | -------------------------------------------------------------------------------- /chapter01/preproc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned n = 23; 4 | 5 | /* брой прости числа, с които разполагаме – изчислени предварително */ 6 | #define K 25 7 | unsigned prime[K] = { 8 | 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 9 | 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}; 10 | 11 | /* проверяваме дали число е просто, като проверяваме дали има делители сред 12 | * числата от масива prime[] 13 | */ 14 | char checkprime(unsigned n) 15 | { unsigned i = 0; 16 | while (i < K && prime[i] * prime[i] <= n) { 17 | if (n % prime[i] == 0) return 0; 18 | i++; 19 | } 20 | return 1; 21 | } 22 | 23 | int main(void) 24 | { if (checkprime(n)) 25 | printf("Числото %u е просто. \n", n); 26 | else 27 | printf("Числото %u е съставно. \n", n); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /chapter01/prime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const unsigned n = 23; 5 | 6 | /* Функцията връща 1 ако n е просто и 0 ако n е съставно */ 7 | char isPrime(unsigned n) 8 | { unsigned i = 2; 9 | if (n == 2) return 1; 10 | while (i <= sqrt(n)) { 11 | if (n % i == 0) return 0; 12 | i++; 13 | } 14 | return 1; 15 | } 16 | 17 | int main(void) { 18 | if (isPrime(n)) 19 | printf("Числото %u е просто.\n", n); 20 | else 21 | printf("Числото %u е съставно.\n", n); 22 | } 23 | -------------------------------------------------------------------------------- /chapter01/print.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned n = 7892; 4 | 5 | int main(void) 6 | { unsigned dig[10], i, k = 0; 7 | while (n > 0) { 8 | dig[k] = n % 10; 9 | n = n / 10; 10 | k++; 11 | } 12 | for (i = k; i > 0; i--) printf("%u ", dig[i-1]); 13 | printf("\n"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /chapter01/print1.c: -------------------------------------------------------------------------------- 1 | #include 2 | const unsigned n = 5; 3 | 4 | void printRed(unsigned k, unsigned long result) 5 | { printf("%lu ", result); 6 | if (k < n) printRed(k + 1, result * 10); 7 | printf("%lu ", result); 8 | } 9 | 10 | int main(void) { 11 | printRed(1, 10); 12 | printf("\n"); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /chapter01/print2.c: -------------------------------------------------------------------------------- 1 | #include 2 | const unsigned n = 5; 3 | unsigned k = 0; 4 | 5 | void printRed(unsigned long result) 6 | { k++; 7 | printf("%lu ", result); 8 | if (k < n) printRed(result * 10); 9 | printf("%lu ", result); 10 | } 11 | 12 | int main(void) { 13 | printRed(10); 14 | printf("\n"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /chapter01/print3.c: -------------------------------------------------------------------------------- 1 | #include 2 | const unsigned n = 5; 3 | unsigned long result = 1; 4 | unsigned k = 0; 5 | 6 | void printRed(void) 7 | { k++; 8 | result *= 10; 9 | printf("%lu ", result); 10 | if (k < n) printRed(); 11 | printf("%lu ", result); 12 | result /= 10; 13 | } 14 | 15 | int main(void) { 16 | printRed(); 17 | printf("\n"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /chapter01/printrec.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned n = 7892; 4 | 5 | void printN(unsigned n) 6 | { if (n >= 10) printN(n / 10); 7 | printf("%u ", n % 10); 8 | } 9 | 10 | int main() { 11 | printN(n); printf("\n"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /chapter01/rom2dec.c: -------------------------------------------------------------------------------- 1 | #define MAX_ROMAN_LEN 20 2 | 3 | #include 4 | #include 5 | 6 | const char *roman1_9[] = {"", "A", "AA", "AAA", "AB", "B", "BA", "BAA", "BAAA", "AC"}; 7 | const char *romanDigits[] = {"IVX", "XLC", "CDM", "M" }; 8 | 9 | const char *roman2test = "MCMLXXXIX"; 10 | 11 | void getRomanDigit(char *rslt, char x, unsigned char power) 12 | { const char *pch; 13 | for (pch = roman1_9[x]; '\0' != *pch; pch++) 14 | *rslt++ = romanDigits[power][*pch - 'A']; 15 | *rslt = '\0'; 16 | } 17 | 18 | char *decimal2Roman(char *rslt, unsigned x) 19 | { unsigned char power; 20 | char buf[10]; 21 | char oldRslt[MAX_ROMAN_LEN]; 22 | for (*rslt = '\0', power = 0; x > 0; power++, x /= 10) { 23 | getRomanDigit(buf, (char)(x % 10), power); 24 | strcpy(oldRslt, rslt); 25 | strcpy(rslt,buf); 26 | strcat(rslt,oldRslt); 27 | } 28 | return rslt; 29 | } 30 | 31 | unsigned roman2Decimal(const char *roman, char *error) 32 | { unsigned rslt, value, old; 33 | const char *saveRoman = roman; 34 | char buf[MAX_ROMAN_LEN]; 35 | 36 | old = 1000; rslt = 0; 37 | while ('\0' != *roman) { 38 | switch (*roman++) { 39 | case 'I': value = 1; break; 40 | case 'V': value = 5; break; 41 | case 'X': value = 10; break; 42 | case 'L': value = 50; break; 43 | case 'C': value = 100; break; 44 | case 'D': value = 500; break; 45 | case 'M': value = 1000; break; 46 | default: 47 | *error = 1; 48 | return (unsigned)(-1); 49 | } 50 | rslt += value; 51 | if (value > old) 52 | rslt -= 2*old; 53 | old = value; 54 | } 55 | return (*error = strcmp(saveRoman,decimal2Roman(buf,rslt))) 56 | ? (unsigned)(-1) : rslt; 57 | } 58 | 59 | int main(void) { 60 | unsigned decimal; 61 | char error; 62 | decimal = roman2Decimal(roman2test,&error); 63 | if (error) printf("Некоректнo римско число!"); 64 | else printf("Числото в десетична бройна система е %u", decimal); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /chapter01/runproc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 10000 4 | const unsigned n = 500; 5 | 6 | unsigned primes[MAXN], pN = 0; 7 | 8 | char isPrime(unsigned n) 9 | { unsigned i = 0; 10 | while (i < pN && primes[i] * primes[i] <= n) { 11 | if (n % primes[i] == 0) return 0; 12 | i++; 13 | } 14 | return 1; 15 | } 16 | 17 | void findPrimes(unsigned n) 18 | { unsigned i = 2; 19 | while (i < n) { 20 | if (isPrime(i)) { 21 | primes[pN] = i; 22 | pN++; 23 | printf("%5u", i); 24 | } 25 | i++; 26 | } 27 | } 28 | 29 | int main(void) { 30 | findPrimes(n); 31 | printf("\n"); 32 | return 0; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /chapter01/sieve.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 30000 4 | 5 | const unsigned n = 200; 6 | 7 | char sieve[MAXN]; 8 | 9 | void eratosten(unsigned n) 10 | { unsigned j, i = 2; 11 | while (i <= n) { 12 | if (sieve[i] == 0) { 13 | printf("%5u", i); 14 | j = i; 15 | while (j <= n) { 16 | sieve[j] = 1; 17 | j += i; 18 | } 19 | } 20 | i++; 21 | } 22 | } 23 | 24 | int main(void) { 25 | unsigned i; 26 | for (i = 0; i < n; i++) sieve[i] = 0; 27 | eratosten(n); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /chapter01/sum1.c: -------------------------------------------------------------------------------- 1 | unsigned sum(unsigned n) 2 | { unsigned i, s = 0; 3 | for (i = 1; i <= n; i++) s += i; 4 | return s; 5 | } 6 | -------------------------------------------------------------------------------- /chapter01/sum2.c: -------------------------------------------------------------------------------- 1 | int a[n]; 2 | 3 | int sum(void) 4 | { unsigned int i; 5 | int s = 0; 6 | for (i = 0; i < n; i++) s += a[i]; 7 | return s; 8 | } 9 | -------------------------------------------------------------------------------- /chapter01/summat.c: -------------------------------------------------------------------------------- 1 | for (i = 0; i < m; i++) 2 | for (j = 0; j < n; j++) C[i][j] = A[i][j] + B[i][j]; 3 | -------------------------------------------------------------------------------- /chapter01/sumzero.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Брой числа в редицата */ 5 | const unsigned n = 8; 6 | /* Редица */ 7 | int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 8 | /* Търсена сума */ 9 | int sum = 0; 10 | 11 | void checkSol(void) 12 | { unsigned i; 13 | int tempSum = 0; 14 | for (i = 0; i < n; i++) tempSum += a[i]; 15 | if (tempSum == sum) { /* намерено е решение => отпечатваме го */ 16 | for (i = 0; i < n; i++) 17 | if (a[i] > 0) printf("+%d ", a[i]); 18 | else printf("%d ", a[i]); 19 | printf(" = %d\n", tempSum); 20 | } 21 | } 22 | 23 | void variate(unsigned i) 24 | { if (i >= n) { 25 | checkSol(); 26 | return; 27 | } 28 | a[i] = abs(a[i]); variate(i + 1); 29 | a[i] = -abs(a[i]); variate(i + 1); 30 | } 31 | 32 | int main(void) { 33 | variate(0); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /chapter01/variate.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | /* Вариации на n елемента от клас k */ 6 | const unsigned n = 4; 7 | const unsigned k = 2; 8 | 9 | int taken[MAXN]; 10 | 11 | void print(unsigned i) 12 | { unsigned k; 13 | printf("( "); 14 | for (k = 0; k <= i - 1; k++) printf("%u ", taken[k] + 1); 15 | printf(")\n"); 16 | } 17 | 18 | /* рекурсия */ 19 | void variate(unsigned i) 20 | { unsigned j; 21 | /* без if (i>=k) и return; тук (а само print(i); ако искаме всички 22 | * генерирания с дължина 1,2, …, k, а не само вариациите с дължина k */ 23 | if (i >= k) { print(i); return; } 24 | for (j = 0; j < n; j++) { 25 | /* if (allowed(k)) { */ 26 | taken[i] = j; 27 | variate(i + 1); 28 | } 29 | } 30 | 31 | int main(void) { 32 | variate(0); 33 | return 0; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /chapter02/queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX 10 4 | 5 | typedef int data; 6 | data queue[MAX]; 7 | int front, rear, empty; 8 | 9 | void init(void) { front = rear = 0; empty = 1; } 10 | 11 | void put(data i) 12 | { if (front == rear && !empty) { /* Проверка за препълване */ 13 | /* препълване - индексите са равни, а опашката не е празна */ 14 | fprintf(stderr, "Препълване! \n"); 15 | return; 16 | } 17 | queue[rear++] = i; 18 | if (rear >= MAX) rear = 0; 19 | empty = 0; 20 | } 21 | 22 | data get(void) 23 | { data x; 24 | if (empty) { /* Проверка за празна опашка */ 25 | fprintf(stderr, "Опашката е празна! \n"); 26 | return 0; 27 | } 28 | x = queue[front++]; 29 | if (front >= MAX) front = 0; 30 | if (front == rear) empty = 1; 31 | return x; 32 | } 33 | 34 | int main(void) { 35 | data p; 36 | int i; 37 | init(); 38 | for (i = 0; i < 2 * MAX; i++) { 39 | put(i); 40 | p = get(); 41 | printf("%d ", p); 42 | } 43 | 44 | printf("\n"); 45 | 46 | /* Това ще причини препълване при последното включване */ 47 | for (i = 0; i < MAX + 1; i++) put(i); 48 | 49 | /* Това ще причини грешка при последното изключване, тъй като опашката е празна */ 50 | for (i = 0; i < MAX + 1; i++) get(); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /chapter02/stack1.c: -------------------------------------------------------------------------------- 1 | // GC-to tuk zasira qko - zashtoto funkciite mi sa ednoredovi 2 | #include 3 | 4 | typedef int data; 5 | data stack[10]; 6 | int top; 7 | 8 | void init(void) { top = 0; } 9 | void push(data i) { stack[top++] = i; } 10 | data pop(void) { return stack[--top]; } 11 | int empty(void) { return(top == 0); } 12 | 13 | int main(void) { 14 | /* ... */ 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /chapter02/stack2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 10 3 | 4 | typedef int data; 5 | data stack[MAX]; 6 | int top; 7 | 8 | void init(void) { top = 0; } 9 | 10 | void push(data i) 11 | { if (MAX == top) 12 | fprintf(stderr, "Препълване на стека! \n"); 13 | else 14 | stack[top++] = i; 15 | } 16 | 17 | data pop(void) 18 | { if (0 == top) { 19 | fprintf(stderr, "Стекът е празен! \n"); 20 | return 0; 21 | } 22 | else 23 | return stack[--top]; 24 | } 25 | 26 | int empty(void) { return (0 == top); } 27 | 28 | int main(void) { 29 | data p; 30 | init(); 31 | 32 | /* Четат се цели числа от клавиатурата до прочитане на 0 и се включват в стека */ 33 | scanf("%d", &p); 34 | while (0 != p) { 35 | push(p); 36 | scanf("%d", &p); 37 | }; 38 | 39 | /* Изключват се последователно всички елементи от стека и се печатат. Това ще 40 | * доведе до отпечатване на първоначално въведената последователност в обратен ред 41 | */ 42 | while (!empty()) printf("%d ", pop()); 43 | printf("\n"); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /chapter03/bubsort1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define TEST_LOOP_CNT 100 9 | 10 | struct CElem { 11 | int key; 12 | /* ............. 13 | Някакви данни 14 | ............. */ 15 | }; 16 | 17 | void swap(struct CElem *x1, struct CElem *x2) 18 | { struct CElem tmp = *x1; *x1 = *x2; *x2 = tmp; } 19 | 20 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 21 | { unsigned i; 22 | srand(time(NULL)); 23 | for (i = 0; i < n; i++) 24 | m[i].key = rand() % n; 25 | } 26 | 27 | void bubbleSort1(struct CElem m[], unsigned n) 28 | { unsigned i, j; 29 | for (i = 1; i < n; i++) 30 | for (j = n-1; j >= i; j--) 31 | if (m[j-1].key > m[j].key) 32 | swap(m+j-1, m+j); 33 | } 34 | 35 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 36 | { unsigned i; 37 | for (i = 0; i < n; i++) 38 | printf("%8d", m[i].key); 39 | } 40 | 41 | void check(const struct CElem m[], 42 | const struct CElem saveM[], 43 | unsigned n) 44 | { unsigned i, j; 45 | char *found; /* третира се като масив от булев тип */ 46 | 47 | /* 1. Проверка за наредба във възходящ ред */ 48 | for (i = 0; i < n-1; i++) 49 | assert(m[i].key <= m[i + 1].key); 50 | 51 | /* 2. Проверка за пермутация на изходните елементи */ 52 | found = (char *) calloc(n + 1, sizeof(*found)); 53 | for (i = 0; i < n; i++) { 54 | for (j = 0; j < n; j++) 55 | if (!found[j] && m[i].key == saveM[j].key) { 56 | found[j] = 1; 57 | break; 58 | } 59 | 60 | assert(j < n); /* Пропада, ако не е намерен съответен */ 61 | } 62 | 63 | free(found); 64 | } 65 | 66 | int main(void) 67 | { struct CElem m[MAX], saveM[MAX]; 68 | unsigned loopInd; 69 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 70 | printf("\n<<<<< Тест %u >>>>>\n", loopInd); 71 | init(m, MAX); 72 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 73 | printf("Масивът преди сортирането:\n"); 74 | print(m, MAX); 75 | bubbleSort1(m, MAX); 76 | printf("Масивът след сортирането:\n"); 77 | print(m, MAX); 78 | check(m, saveM, MAX); 79 | } 80 | return 0; 81 | } -------------------------------------------------------------------------------- /chapter03/bubsort2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define TEST_LOOP_CNT 100 9 | 10 | struct CElem { 11 | int key; 12 | /* ............. 13 | Някакви данни 14 | ............. */ 15 | }; 16 | 17 | void swap(struct CElem *x1, struct CElem *x2) 18 | { struct CElem tmp = *x1; *x1 = *x2; *x2 = tmp; } 19 | 20 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 21 | { unsigned i; 22 | srand(time(NULL)); 23 | for (i = 0; i < n; i++) 24 | m[i].key = rand() % n; 25 | } 26 | 27 | void bubbleSort2(struct CElem m[], unsigned n) 28 | { unsigned i, j, k; 29 | for (i = n; i > 0; i = k) 30 | for (k = j = 0; j < i; j++) 31 | if (m[j].key > m[j+1].key) { 32 | swap(m+j, m+j+1); 33 | k = j; 34 | } 35 | } 36 | 37 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 38 | { unsigned i; 39 | for (i = 0; i < n; i++) 40 | printf("%8d", m[i].key); 41 | } 42 | 43 | void check(const struct CElem m[], 44 | const struct CElem saveM[], 45 | unsigned n) 46 | { unsigned i, j; 47 | char *found; /* третира се като масив от булев тип */ 48 | 49 | /* 1. Проверка за наредба във възходящ ред */ 50 | for (i = 0; i < n-1; i++) 51 | assert(m[i].key <= m[i + 1].key); 52 | 53 | /* 2. Проверка за пермутация на изходните елементи */ 54 | found = (char *) calloc(n + 1, sizeof(*found)); 55 | for (i = 0; i < n; i++) { 56 | for (j = 0; j < n; j++) 57 | if (!found[j] && m[i].key == saveM[j].key) { 58 | found[j] = 1; 59 | break; 60 | } 61 | 62 | assert(j < n); /* Пропада, ако не е намерен съответен */ 63 | } 64 | 65 | free(found); 66 | } 67 | 68 | int main(void) 69 | { struct CElem m[MAX], saveM[MAX]; 70 | unsigned loopInd; 71 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 72 | printf("\n<<<<< Тест %u >>>>>\n", loopInd); 73 | init(m, MAX); 74 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 75 | printf("Масивът преди сортирането:\n"); 76 | print(m, MAX); 77 | bubbleSort2(m, MAX); 78 | printf("Масивът след сортирането:\n"); 79 | print(m, MAX); 80 | check(m, saveM, MAX); 81 | } 82 | return 0; 83 | } -------------------------------------------------------------------------------- /chapter03/count_s.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define FACTOR 5 9 | #define MAX_VALUE (MAX*FACTOR) 10 | #define TEST_LOOP_CNT 100 11 | 12 | void init(unsigned m[], unsigned n) /* Запълва масива със случайни цели числа */ 13 | { unsigned i; 14 | srand(time(NULL)); 15 | for (i = 0; i < n; i++) 16 | m[i] = rand() % n; 17 | } 18 | 19 | void countSort(unsigned m[], unsigned n) /* Сортира чрез броене */ 20 | { unsigned char cnt[MAX_VALUE]; 21 | unsigned i,j; 22 | 23 | /* 0. Инициализиране на множеството */ 24 | for (i = 0; i < MAX_VALUE; i++) 25 | cnt[i] = 0; 26 | 27 | /* 1. Формиране на множеството */ 28 | for (j = 0; j < n; j++) { 29 | assert(m[j] >= 0 && m[j] < MAX_VALUE); 30 | cnt[m[j]]++; 31 | } 32 | 33 | /* 2. Генериране на сортирана последователност */ 34 | for (i = j = 0; i < MAX_VALUE; i++) 35 | while (cnt[i]--) 36 | m[j++] = i; 37 | 38 | assert(j == n); 39 | } 40 | 41 | void print(unsigned m[], unsigned n) /* Извежда ключовете на масива на екрана */ 42 | { unsigned i; 43 | for (i = 0; i < n; i++) 44 | printf("%8u", m[i]); 45 | } 46 | 47 | void check(const unsigned m[], const unsigned saveM[], unsigned n) 48 | { unsigned i, j; 49 | char *found; /* третира се като масив от булев тип */ 50 | 51 | /* 1. Проверка за наредба във възходящ ред */ 52 | for (i = 0; i < n-1; i++) 53 | assert(m[i] <= m[i+1]); 54 | 55 | /* 2. Проверка за пермутация на изходните елементи */ 56 | found = (char *) calloc(n+1,sizeof(*found)); 57 | for (i = 0; i < n; i++) { 58 | for (j = 0; j < n; j++) 59 | if (!found[j] && m[i] == saveM[j]) { 60 | found[j] = 1; 61 | break; 62 | } 63 | assert(j < n); /* Пропада, ако не е намерен съответен */ 64 | } 65 | free(found); 66 | } 67 | 68 | int main(void) { 69 | unsigned m[MAX], saveM[MAX]; 70 | unsigned loopInd; 71 | printf("start -- \n"); 72 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 73 | init(m,MAX); 74 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 75 | printf("Масивът преди сортирането:\n"); 76 | print(m,MAX); 77 | countSort(m,MAX); 78 | printf("Масивът след сортирането:\n"); 79 | print(m,MAX); 80 | check(m,saveM,MAX); 81 | } 82 | return 0; 83 | } -------------------------------------------------------------------------------- /chapter03/insert_s.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define TEST_LOOP_CNT 100 9 | 10 | struct CElem { 11 | int key; 12 | /* ............. 13 | Някакви данни 14 | ............. */ 15 | }; 16 | 17 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 18 | { unsigned i; 19 | srand(time(NULL)); 20 | for (i = 0; i < n; i++) 21 | m[i].key = rand() % n; 22 | } 23 | 24 | void straightInsertion(struct CElem m[], unsigned n) 25 | { struct CElem x; 26 | unsigned i; 27 | int j; 28 | for (i = 0; i < n; i++) { 29 | x = m[i]; 30 | j = i-1; 31 | while (x.key < m[j].key && j >= 0) 32 | m[j+1] = m[j--]; 33 | m[j+1] = x; 34 | } 35 | } 36 | 37 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 38 | { unsigned i; 39 | for (i = 0; i < n; i++) 40 | printf("%8d", m[i].key); 41 | } 42 | 43 | void check(const struct CElem m[], const struct CElem saveM[], unsigned n) 44 | { unsigned i, j; 45 | char *found; /* третира се като масив от булев тип */ 46 | 47 | /* 1. Проверка за наредба във възходящ ред */ 48 | for (i = 0; i < n-1; i++) 49 | assert(m[i].key <= m[i+1].key); 50 | 51 | /* 2. Проверка за пермутация на изходните елементи */ 52 | found = (char *) calloc(n+1,sizeof(*found)); 53 | for (i = 0; i < n; i++) { 54 | for (j = 0; j < n; j++) 55 | if (!found[j] && m[i].key == saveM[j].key) { 56 | found[j] = 1; 57 | break; 58 | } 59 | assert(j < n); /* Пропада, ако не е намерен съответен */ 60 | } 61 | free(found); 62 | } 63 | 64 | int main(void) { 65 | struct CElem m[MAX], saveM[MAX]; 66 | unsigned loopInd; 67 | printf("start -- \n"); 68 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 69 | init(m,MAX); 70 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 71 | printf("Масивът преди сортирането:\n"); 72 | print(m,MAX); 73 | straightInsertion(m,MAX); 74 | printf("Масивът след сортирането:\n"); 75 | print(m,MAX); 76 | check(m,saveM,MAX); 77 | } 78 | return 0; 79 | } -------------------------------------------------------------------------------- /chapter03/inserts2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define TEST_LOOP_CNT 100 9 | 10 | struct CElem { 11 | int key; 12 | /* ............. 13 | Някакви данни 14 | ............. */ 15 | }; 16 | 17 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 18 | { unsigned i; 19 | srand(time(NULL)); 20 | for (i = 1; i <= n; i++) 21 | m[i].key = rand() % n; 22 | } 23 | 24 | void straightInsertion(struct CElem m[], unsigned n) 25 | { unsigned i, j; 26 | struct CElem x; 27 | for (i = 1; i <= n; i++) { 28 | x = m[i]; m[0].key = x.key; 29 | for (j = i - 1; x.key < m[j].key; j--) 30 | m[j+1] = m[j]; 31 | m[j+1] = x; 32 | } 33 | } 34 | 35 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 36 | { unsigned i; 37 | for (i = 1; i <= n; i++) 38 | printf("%8d", m[i].key); 39 | } 40 | 41 | void check(const struct CElem m[], const struct CElem saveM[], unsigned n) 42 | { unsigned i, j; 43 | char *found; /* третира се като масив от булев тип */ 44 | 45 | /* 1. Проверка за наредба във възходящ ред */ 46 | for (i = 1; i < n; i++) 47 | assert(m[i].key <= m[i+1].key); 48 | 49 | /* 2. Проверка за пермутация на изходните елементи */ 50 | found = (char *) calloc(n+1,sizeof(*found)); 51 | for (i = 1; i <= n; i++) { 52 | for (j = 1; j <= n; j++) 53 | if (!found[j] && m[i].key == saveM[j].key) { 54 | found[j] = 1; 55 | break; 56 | } 57 | assert(j <= n); /* Пропада, ако не е намерен съответен */ 58 | } 59 | free(found); 60 | } 61 | 62 | int main(void) { 63 | struct CElem m[MAX+1], saveM[MAX+1]; 64 | unsigned loopInd; 65 | printf("start -- \n"); 66 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 67 | init(m,MAX); 68 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 69 | printf("Масивът преди сортирането:\n"); 70 | print(m,MAX); 71 | straightInsertion(m,MAX); 72 | printf("Масивът след сортирането:\n"); 73 | print(m,MAX); 74 | check(m,saveM,MAX); 75 | } 76 | return 0; 77 | } -------------------------------------------------------------------------------- /chapter03/permsort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define TEST_LOOP_CNT 100 9 | 10 | struct CElem { 11 | int key; 12 | /* ............. 13 | Някакви данни 14 | ............. */ 15 | }; 16 | 17 | void swap(struct CElem *x1, struct CElem *x2) 18 | { struct CElem tmp = *x1; *x1 = *x2; *x2 = tmp; } 19 | 20 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 21 | { unsigned i; 22 | srand(time(NULL)); 23 | for (i = 0; i < n; i++) 24 | m[i].key = i; 25 | for (i = 0; i < n; i++) 26 | swap(m + i, m + rand() % n); 27 | } 28 | 29 | void permSort(struct CElem m[], unsigned n) 30 | { unsigned i; 31 | for (i = 0; i < n; i++) 32 | while (m[i].key != (int)i) 33 | swap(&m[i],&m[m[i].key]); 34 | } 35 | 36 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 37 | { unsigned i; 38 | for (i = 0; i < n ; i++) 39 | printf("%8d", m[i].key); 40 | } 41 | 42 | void check(const struct CElem m[], const struct CElem saveM[], unsigned n) 43 | { unsigned i, j; 44 | char *found; /* третира се като масив от булев тип */ 45 | 46 | /* 1. Проверка за наредба във възходящ ред */ 47 | for (i = 0; i < n-1; i++) 48 | assert(m[i].key <= m[i+1].key); 49 | 50 | /* 2. Проверка за пермутация на изходните елементи */ 51 | found = (char *) calloc(n,sizeof(*found)); 52 | for (i = 0; i < n; i++) { 53 | for (j = 0; j < n; j++) 54 | if (!found[j] && m[i].key == saveM[j].key) { 55 | found[j] = 1; 56 | break; 57 | } 58 | assert(j < n); /* Пропада, ако не е намерен съответен */ 59 | } 60 | 61 | free(found); 62 | } 63 | 64 | int main(void) { 65 | struct CElem m[MAX], saveM[MAX]; 66 | unsigned loopInd; 67 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 68 | printf("\n<<<<< Тест %u >>>>>\n", loopInd); 69 | init(m,MAX); 70 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 71 | printf("Масивът преди сортирането:\n"); 72 | print(m,MAX); 73 | permSort(m,MAX); 74 | printf("Масивът след сортирането:\n"); 75 | print(m,MAX); 76 | check(m,saveM,MAX); 77 | } 78 | return 0; 79 | } -------------------------------------------------------------------------------- /chapter03/selsort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX 100 8 | #define TEST_LOOP_CNT 100 9 | 10 | struct CElem { 11 | int key; 12 | /* ............. 13 | Някакви данни 14 | ............. */ 15 | }; 16 | 17 | void swap(struct CElem *x1, struct CElem *x2) 18 | { struct CElem tmp = *x1; *x1 = *x2; *x2 = tmp; } 19 | 20 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 21 | { unsigned i; 22 | srand(time(NULL)); 23 | for (i = 0; i < n; i++) 24 | m[i].key = rand() % n; 25 | } 26 | 27 | void straightSelection(struct CElem m[], unsigned n) 28 | { unsigned i, j; 29 | for (i = 0; i < n-1; i++) 30 | for (j = i+1; j <= n; j++) 31 | if (m[i].key > m[j].key) 32 | swap(m+i, m+j); 33 | } 34 | 35 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 36 | { unsigned i; 37 | for (i = 0; i < n; i++) 38 | printf("%8d", m[i].key); 39 | } 40 | 41 | void check(const struct CElem m[], 42 | const struct CElem saveM[], 43 | unsigned n) 44 | { unsigned i, j; 45 | char *found; /* третира се като масив от булев тип */ 46 | 47 | /* 1. Проверка за наредба във възходящ ред */ 48 | for (i = 0; i < n-1; i++) 49 | assert(m[i].key <= m[i + 1].key); 50 | 51 | /* 2. Проверка за пермутация на изходните елементи */ 52 | found = (char *) calloc(n + 1, sizeof(*found)); 53 | for (i = 0; i < n; i++) { 54 | for (j = 0; j < n; j++) 55 | if (!found[j] && m[i].key == saveM[j].key) { 56 | found[j] = 1; 57 | break; 58 | } 59 | 60 | assert(j < n); /* Пропада, ако не е намерен съответен */ 61 | } 62 | 63 | free(found); 64 | } 65 | 66 | int main(void) 67 | { struct CElem m[MAX], saveM[MAX]; 68 | unsigned loopInd; 69 | for (loopInd = 1; loopInd <= TEST_LOOP_CNT; loopInd++) { 70 | printf("\n<<<<< Тест %u >>>>>\n", loopInd); 71 | init(m, MAX); 72 | memcpy(saveM, m, sizeof(m)); /* Запазва се копие на масива */ 73 | printf("Масивът преди сортирането:\n"); 74 | print(m, MAX); 75 | straightSelection(m, MAX); 76 | printf("Масивът след сортирането:\n"); 77 | print(m, MAX); 78 | check(m, saveM, MAX); 79 | } 80 | return 0; 81 | } -------------------------------------------------------------------------------- /chapter03/setsort2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX 100 7 | #define FACTOR 5 8 | #define MAX_VALUE (MAX*FACTOR) 9 | #define NO_INDEX (unsigned)(-1) 10 | 11 | struct CElem { 12 | int key; 13 | /* ............. 14 | Някакви данни 15 | ............. */ 16 | }; 17 | 18 | void init(struct CElem m[], unsigned n) /* Запълва масива със случайни цели числа */ 19 | { unsigned i; 20 | 21 | /* 1. Запълване със случайни стойности в нарастващ ред */ 22 | srand(time(NULL)); 23 | m[0].key = rand() % FACTOR; 24 | for (i = 1; i < n; i++) 25 | m[i].key = 1 + m[i-1].key + rand() % FACTOR; 26 | 27 | /* 2. Разменяме елементи */ 28 | for (i = 1; i < n; i++) { 29 | unsigned ind1, ind2; 30 | struct CElem tmp; 31 | 32 | /* 2.1. Избиране на два случайни индекса */ 33 | ind1 = rand() % n; 34 | ind2 = rand() % n; 35 | 36 | /* 2.2. Разменяме ги */ 37 | tmp = m[ind1]; 38 | m[ind1] = m[ind2]; 39 | m[ind2] = tmp; 40 | } 41 | 42 | } 43 | 44 | void print(struct CElem m[], unsigned n) /* Извежда ключовете на масива на екрана */ 45 | { unsigned i; 46 | for (i = 0; i < n; i++) 47 | printf("%8d", m[i].key); 48 | } 49 | 50 | void do4Elem(const struct CElem e) 51 | { printf("%8d", e.key); } 52 | 53 | void setSort(struct CElem m[], unsigned n) /* Сортира масив с използване на множество */ 54 | { unsigned indSet[MAX_VALUE]; /* Индексно множество */ 55 | unsigned i,j; 56 | 57 | /* 0. Инициализиране на множеството */ 58 | for (i = 0; i < MAX_VALUE; i++) 59 | indSet[i] = NO_INDEX; 60 | 61 | /* 1. Формиране на множеството */ 62 | for (j = 0; j < n; j++) { 63 | assert(m[j].key >= 0 && m[j].key < MAX_VALUE); 64 | assert(NO_INDEX == indSet[m[j].key]); 65 | indSet[m[j].key] = j; 66 | } 67 | 68 | /* 2. Генериране на сортирана последователност */ 69 | for (i = j = 0; i < MAX_VALUE; i++) 70 | if (NO_INDEX != indSet[i]) 71 | do4Elem(m[indSet[i]]); 72 | } 73 | 74 | int main(void) { 75 | struct CElem m[MAX]; 76 | init(m, MAX); 77 | printf("Масивът преди сортирането:\n"); 78 | print(m,MAX); 79 | printf("Масивът след сортирането:\n"); 80 | setSort(m, MAX); 81 | return 0; 82 | } -------------------------------------------------------------------------------- /chapter04/binsear0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | #define NOT_FOUND (unsigned)(-1) 6 | 7 | #define DataType int 8 | struct CElem { 9 | int key; 10 | DataType data; 11 | /* ... */ 12 | } m[MAX]; /* Масив от записи */ 13 | unsigned n; /* Брой елементи в масива */ 14 | 15 | void binInit(void) { n = 0; } /* Инициализация */ 16 | 17 | void sort(void) /* Сортиране */ 18 | { unsigned i,j; 19 | for (i = 0; i < n-1; i++) 20 | for (j = i + 1; j < n; j++) 21 | if (m[i].key > m[j].key) { 22 | struct CElem tmp = m[i]; 23 | m[i] = m[j]; 24 | m[j] = tmp; 25 | } 26 | } 27 | 28 | unsigned binSearch(int key, int l, int r) /* Извършва двоично търсене */ 29 | { int mid; 30 | if (l > r) 31 | return NOT_FOUND; 32 | mid = (l + r) / 2; 33 | if (key < m[mid].key) 34 | return binSearch(key,l,mid-1); 35 | else if (key > m[mid].key) 36 | return binSearch(key,mid+1,r); 37 | else 38 | return mid; 39 | } 40 | 41 | void binInsert(int key, int data) /* Добавяне на нов елемент */ 42 | { m[n].key = key; 43 | m[n++].data = data; 44 | } 45 | 46 | void binPrint(void) /* Извежда списъка на екрана */ 47 | { unsigned i; 48 | char buf[9]; 49 | for (i = 0; i < n; i++) { 50 | sprintf(buf, "%d|%d", m[i].key, m[i].data); 51 | printf("%8s", buf); 52 | } 53 | } 54 | 55 | void performSearchTest(void) 56 | { unsigned ind, elem2Search; 57 | for (elem2Search = 0; elem2Search < 2*MAX; elem2Search++) { 58 | printf("Търсим елемент с ключ %u.\n", elem2Search); 59 | if (NOT_FOUND == (ind = binSearch(elem2Search, 0, n-1))) 60 | printf("%s","Елемент с такъв ключ не съществува!\n"); 61 | else 62 | printf("%Елементът е намерен! Стойност на инф. част: %d\n", m[ind].data); 63 | } 64 | } 65 | 66 | int main(void) { 67 | unsigned ind; 68 | binInit(); 69 | for (ind = 0; ind < MAX; ind++) 70 | binInsert(rand() % (MAX*2), ind); 71 | sort(); 72 | printf("Списъкът съдържа следните елементи: \n"); binPrint(); 73 | printf("\nТестване:\n"); 74 | performSearchTest(); 75 | return 0; 76 | } -------------------------------------------------------------------------------- /chapter04/binsear1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | #define NOT_FOUND (unsigned)(-1) 6 | 7 | #define DataType int 8 | struct CElem { 9 | int key; 10 | DataType data; 11 | /* ... */ 12 | } m[MAX]; /* Масив от записи */ 13 | unsigned n; /* Брой елементи в масива */ 14 | 15 | void binInit(void) { n = 0; } /* Инициализация */ 16 | 17 | void sort(void) /* Сортиране */ 18 | { unsigned i,j; 19 | for (i = 0; i < n-1; i++) 20 | for (j = i + 1; j < n; j++) 21 | if (m[i].key > m[j].key) { 22 | struct CElem tmp = m[i]; 23 | m[i] = m[j]; 24 | m[j] = tmp; 25 | } 26 | } 27 | 28 | unsigned binSearch(int key) /* Извършва двоично търсене */ 29 | { int l = 0, r = n-1, mid; 30 | while (l <= r) { 31 | mid = (l + r) / 2; 32 | if (key < m[mid].key) 33 | r = mid - 1; 34 | else if (key > m[mid].key) 35 | l = mid + 1; 36 | else 37 | return mid; 38 | } 39 | return NOT_FOUND; 40 | } 41 | 42 | void binInsert(int key, int data) /* Добавяне на нов елемент */ 43 | { m[n].key = key; 44 | m[n++].data = data; 45 | } 46 | 47 | void binPrint(void) /* Извежда списъка на екрана */ 48 | { unsigned i; 49 | char buf[9]; 50 | for (i = 0; i < n; i++) { 51 | sprintf(buf, "%d|%d", m[i].key, m[i].data); 52 | printf("%8s", buf); 53 | } 54 | } 55 | 56 | void performSearchTest(void) 57 | { unsigned ind, elem2Search; 58 | for (elem2Search = 0; elem2Search < 2*MAX; elem2Search++) { 59 | printf("Търсим елемент с ключ %u.\n", elem2Search); 60 | if (NOT_FOUND == (ind = binSearch(elem2Search))) 61 | printf("%s","Елемент с такъв ключ не съществува!\n"); 62 | else 63 | printf("%Елементът е намерен! Стойност на инф. част: %d\n", m[ind].data); 64 | } 65 | } 66 | 67 | int main(void) { 68 | unsigned ind; 69 | binInit(); 70 | for (ind = 0; ind < MAX; ind++) 71 | binInsert(rand() % (MAX*2), ind); 72 | sort(); 73 | printf("Списъкът съдържа следните елементи: \n"); binPrint(); 74 | printf("\nТестване:\n"); 75 | performSearchTest(); 76 | return 0; 77 | } -------------------------------------------------------------------------------- /chapter04/binsear2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | #define NOT_FOUND (unsigned)(-1) 6 | 7 | #define DataType int 8 | struct CElem { 9 | int key; 10 | DataType data; 11 | /* ... */ 12 | } m[MAX]; /* Масив от записи */ 13 | unsigned n; /* Брой елементи в масива */ 14 | 15 | void binInit(void) { n = 0; } /* Инициализация */ 16 | 17 | void sort(void) /* Сортиране */ 18 | { unsigned i,j; 19 | for (i = 0; i < n-1; i++) 20 | for (j = i + 1; j < n; j++) 21 | if (m[i].key > m[j].key) { 22 | struct CElem tmp = m[i]; 23 | m[i] = m[j]; 24 | m[j] = tmp; 25 | } 26 | } 27 | 28 | unsigned getMaxPower2(unsigned k) 29 | { unsigned pow2; 30 | for (pow2 = 1; pow2 <= k; pow2 <<= 1) ; 31 | return pow2 >> 1; 32 | } 33 | 34 | unsigned binSearch(int key) /* Извършва двоично търсене */ 35 | { unsigned i, l, ind; 36 | i = getMaxPower2(n); 37 | l = m[i].key >= key ? 0 : n - i + 1; 38 | while (i > 0) { 39 | i = i >> 1; 40 | ind = l + i; 41 | if (m[ind].key == key) 42 | return ind; 43 | else if (m[ind].key < key) 44 | l = ind; 45 | } 46 | return NOT_FOUND; 47 | } 48 | 49 | void binInsert(int key, int data) /* Добавяне на нов елемент */ 50 | { m[n].key = key; 51 | m[n++].data = data; 52 | } 53 | 54 | void binPrint(void) /* Извежда списъка на екрана */ 55 | { unsigned i; 56 | char buf[9]; 57 | for (i = 0; i < n; i++) { 58 | sprintf(buf, "%d|%d", m[i].key, m[i].data); 59 | printf("%8s", buf); 60 | } 61 | } 62 | 63 | void performSearchTest(void) 64 | { unsigned ind, elem2Search; 65 | for (elem2Search = 0; elem2Search < 2*MAX; elem2Search++) { 66 | printf("Търсим елемент с ключ %u.\n", elem2Search); 67 | if (NOT_FOUND == (ind = binSearch(elem2Search))) 68 | printf("%s","Елемент с такъв ключ не съществува!\n"); 69 | else 70 | printf("%Елементът е намерен! Стойност на инф. част: %d\n", m[ind].data); 71 | } 72 | } 73 | 74 | int main(void) { 75 | unsigned ind; 76 | binInit(); 77 | for (ind = 0; ind < MAX; ind++) 78 | binInsert(rand() % (MAX*2), ind); 79 | sort(); 80 | printf("Списъкът съдържа следните елементи: \n"); binPrint(); 81 | printf("\nТестване:\n"); 82 | performSearchTest(); 83 | return 0; 84 | } -------------------------------------------------------------------------------- /chapter04/jumpsear.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | #define NOT_FOUND (unsigned)(-1) 6 | 7 | #define DataType int 8 | struct CElem { 9 | int key; 10 | DataType data; 11 | /* ... */ 12 | } m[MAX]; /* Масив от записи */ 13 | unsigned n; /* Брой елементи в масива */ 14 | 15 | const unsigned step = 10; 16 | 17 | void jmpInit(void) { n = 0; } /* Инициализация */ 18 | 19 | void sort(void) /* Сортиране */ 20 | { unsigned i,j; 21 | for (i = 0; i < n-1; i++) 22 | for (j = i + 1; j < n; j++) 23 | if (m[i].key > m[j].key) { 24 | struct CElem tmp = m[i]; 25 | m[i] = m[j]; 26 | m[j] = tmp; 27 | } 28 | } 29 | 30 | unsigned seqSearch(unsigned l, unsigned r, int key) /* Последователно търсене */ 31 | { while (l <= r) 32 | if (m[l++].key == key) 33 | return l-1; 34 | return NOT_FOUND; 35 | } 36 | 37 | unsigned jmpSearch(int key, unsigned step) /* Търсене със скокове */ 38 | { unsigned ind; 39 | for (ind = 0; ind < n && m[ind].key < key; ind += step) ; 40 | return seqSearch(ind + 1 < step ? 0 : ind + 1 - step, n < ind ? n : ind, key); 41 | } 42 | 43 | void jmpInsert(int key, int data) /* Добавяне на нов елемент */ 44 | { m[n].key = key; 45 | m[n++].data = data; 46 | } 47 | 48 | void jmpPrint(void) /* Извежда списъка на екрана */ 49 | { unsigned i; 50 | char buf[9]; 51 | for (i = 0; i < n; i++) { 52 | sprintf(buf, "%d|%d", m[i].key, m[i].data); 53 | printf("%8s", buf); 54 | } 55 | } 56 | 57 | void performSearchTest(void) 58 | { unsigned ind, elem2Search; 59 | for (elem2Search = 0; elem2Search < 2*MAX; elem2Search++) { 60 | printf("Търсим елемент с ключ %u.\n", elem2Search); 61 | if (NOT_FOUND == (ind = jmpSearch(elem2Search,step))) 62 | printf("%s","Елемент с такъв ключ не съществува!\n"); 63 | else 64 | printf("%Елементът е намерен! Стойност на инф. част: %d\n", m[ind].data); 65 | } 66 | } 67 | 68 | int main(void) { 69 | unsigned ind; 70 | jmpInit(); 71 | for (ind = 0; ind < MAX; ind++) 72 | jmpInsert(rand() % (MAX*2), ind); 73 | sort(); 74 | printf("Списъкът съдържа следните елементи: \n"); jmpPrint(); 75 | printf("\nТестване:\n"); 76 | performSearchTest(); 77 | return 0; 78 | } -------------------------------------------------------------------------------- /chapter04/reorder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | 5 | #define DataType int 6 | struct CElem { 7 | int key; 8 | DataType data; 9 | struct CElem *next; 10 | /* ... */ 11 | } *head; 12 | 13 | void listInit(void) { head = NULL; } /* Инициализация */ 14 | 15 | void listInsert(int key, DataType data) /* Добавя нов елемент */ 16 | { struct CElem *q = (struct CElem *) malloc(sizeof *head); 17 | q->key = key; q->data = data; 18 | q->next = head; head = q; 19 | } 20 | 21 | struct CElem *listSearch(int key) /* Последователно търсене с преподреждане */ 22 | { struct CElem *q, *p = head; 23 | if (NULL == head) 24 | return NULL; 25 | if (head->key == key) return head; 26 | for (q = head->next; q != NULL; ) 27 | if (q->key != key) { 28 | p = q; 29 | q = q->next; 30 | } 31 | else { 32 | p->next = q->next; 33 | q->next = head; 34 | return (head = q); 35 | } 36 | return NULL; 37 | } 38 | 39 | void listPrint(void) /* Извежда списъка на екрана */ 40 | { struct CElem *q; 41 | char buf[9]; 42 | for (q = head; q != NULL; q = q->next) { 43 | sprintf(buf, "%d|%d", q->key, q->data); 44 | printf("%8s", buf); 45 | } 46 | } 47 | 48 | void performSearchTest(void) 49 | { unsigned elem2Search; 50 | struct CElem *p; 51 | 52 | for (elem2Search = 0; elem2Search < 2*MAX; elem2Search++) { 53 | printf("Търсим елемент с ключ %u.\n", elem2Search); 54 | if (NULL == (p = listSearch(elem2Search))) 55 | printf("%s","Елемент с такъв ключ не съществува!\n"); 56 | else 57 | printf("%Елементът е намерен! Стойност на инф. част: %d\n", p->data); 58 | } 59 | } 60 | 61 | int main(void) { 62 | unsigned ind; 63 | listInit(); 64 | for (ind = 0; ind < MAX; ind++) 65 | listInsert(rand() % (MAX*2), ind); 66 | printf("Списъкът съдържа следните елементи: \n"); listPrint(); 67 | printf("\nТестване:\n"); 68 | performSearchTest(); 69 | printf("Списъкът след търсенето: \n"); listPrint(); 70 | return 0; 71 | } -------------------------------------------------------------------------------- /chapter04/seq_arr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | 6 | #define DataType int 7 | struct CElem { 8 | int key; 9 | DataType data; 10 | /* ... */ 11 | } m[MAX + 1]; /* Масив от записи */ 12 | unsigned n; /* Брой елементи в масива */ 13 | 14 | void seqInit(void) { n = 0; } /* Инициализация */ 15 | 16 | unsigned seqSearch(int key) /* Последователно търсене */ 17 | { unsigned x; 18 | m[0].key = key; /* Ограничител */ 19 | for (x = n + 1; key != m[--x].key; ) ; 20 | return x; 21 | } 22 | 23 | void seqInsert(int key, DataType data) /* Добавя нов елемент */ 24 | { m[++n].key = key; 25 | m[n].data = data; 26 | } 27 | 28 | void seqPrint(void) /* Извежда списъка на екрана */ 29 | { unsigned i; 30 | char buf[9]; 31 | for (i = 1; i <= n; i++) { 32 | sprintf(buf, "%d|%d", m[i].key, m[i].data); 33 | printf("%8s", buf); 34 | } 35 | } 36 | 37 | void performSearchTest(void) 38 | { unsigned ind, elem2Search; 39 | 40 | for (elem2Search = 0; elem2Search < 2*MAX; elem2Search++) { 41 | printf("Търсим елемент с ключ %u.\n", elem2Search); 42 | if (0 == (ind = seqSearch(elem2Search))) 43 | printf("%s","Елемент с такъв ключ не съществува!\n"); 44 | else 45 | printf("%Елементът е намерен! Стойност на инф. част: %d\n", m[ind].data); 46 | } 47 | } 48 | 49 | int main(void) { 50 | unsigned ind; 51 | seqInit(); 52 | for (ind = 0; ind < MAX; ind++) 53 | seqInsert(rand() % (MAX*2), ind); 54 | printf("Списъкът съдържа следните елементи: \n"); seqPrint(); 55 | printf("\nТестване:\n"); 56 | performSearchTest(); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /chapter05/a-center.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 6; 8 | /* Матрица на теглата на графа */ 9 | int A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0, 0 }, 11 | { 0, 0, 1, 0, 1, 0 }, 12 | { 0, 0, 0, 1, 0, 0 }, 13 | { 0, 0, 0, 0, 1, 0 }, 14 | { 0, 1, 0, 0, 0, 1 }, 15 | { 1, 0, 0, 0, 0, 0 } 16 | }; 17 | 18 | const MAX_VALUE = 10000; 19 | 20 | /* Намира дължината на минималния път между всяка двойка върхове */ 21 | void floyd(void) 22 | { unsigned i, j, k; 23 | /* стойностите 0 се променят на MAX_VALUE */ 24 | for (i = 0; i < n; i++) 25 | for (j = 0; j < n; j++) 26 | if (A[i][j] == 0) A[i][j] = MAX_VALUE; 27 | /* Алгоритъм на Флойд */ 28 | for (k = 0; k < n; k++) 29 | for (i = 0; i < n; i++) 30 | for (j = 0; j < n; j++) 31 | if (A[i][j] > (A[i][k] + A[k][j])) 32 | A[i][j] = A[i][k] + A[k][j]; 33 | 34 | for (i = 0; i < n; i++) A[i][i] = 0; 35 | } 36 | 37 | void findCenter(void) 38 | { unsigned i, j, min, max, center; 39 | min = MAX_VALUE; 40 | /* Sot(Xi) = max { Vj [d(Xi, Xj)+d[Xj,Xi])] }, Xj О V Центърът е този връх X* за 41 | * който Sot(X*) е минимално 42 | */ 43 | for (i = 0; i < n; i++) { 44 | max = A[i][0] + A[0][i]; 45 | for (j = 0; j < n; j++) 46 | if ((i != j) && ((A[i][j] + A[j][i]) > max)) max = (A[i][j] + A[j][i]); 47 | if (max < min) { 48 | min = max; center = i; 49 | } 50 | } 51 | printf("Центърът на графа е връх %u\n", center + 1); 52 | printf("Радиусът на графа е %u\n", min); 53 | } 54 | 55 | int main(void) { 56 | floyd(); 57 | findCenter(); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /chapter05/allcyc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 10; 8 | 9 | /* Графът представен с матрица на съседство: 0 - няма ребро; 1 – има ребро; 10 | * По-късно в същата матрица с 2 ще маркираме ребрата на покриващото дърво на графа. 11 | */ 12 | char A[MAXN][MAXN] = { 13 | { 0, 1, 0, 0, 0, 0 }, 14 | { 1, 0, 1, 1, 0, 0 }, 15 | { 0, 1, 0, 1, 0, 0 }, 16 | { 0, 1, 1, 0, 1, 1 }, 17 | { 0, 0, 0, 1, 0, 1 }, 18 | { 0, 0, 0, 1, 1, 0 } 19 | }; 20 | 21 | char used[MAXN]; 22 | unsigned cycle[MAXN], d; 23 | 24 | /* Намира произволно покриващо дърво */ 25 | void DFS(unsigned v) 26 | { unsigned i; 27 | used[v] = 1; 28 | for (i = 0; i < n; i++) 29 | if (!used[i] && A[v][i]) { 30 | A[v][i] = 2; 31 | A[i][v] = 2; 32 | DFS(i); 33 | } 34 | } 35 | 36 | /* Опечатва намерен цикъл */ 37 | void printCycle(void) 38 | { unsigned k, i; 39 | for (k = 0; k < d; k++) printf("%u ", cycle[k] + 1); 40 | printf("\n"); 41 | } 42 | 43 | /* Намиране на един цикъл спрямо намереното покриващо дърво */ 44 | void DFS2(unsigned v, unsigned u) 45 | { unsigned k, i; 46 | if (v == u) { printCycle(); return; } 47 | used[v] = 1; 48 | for (i = 0; i < n; i++) 49 | if (!used[i] && 2==A[v][i]) { 50 | cycle[d++] = i; 51 | DFS2(i, u); 52 | d--; 53 | } 54 | } 55 | 56 | int main(void) { 57 | unsigned i, j, k; 58 | DFS(0); 59 | printf("Елементарните(простите) цикли в графа са: \n"); 60 | for (i = 0; i < n - 1; i++) 61 | for (j = i + 1; j < n; j++) 62 | if (1 == A[i][j]) { 63 | for (k = 0; k < n; k++) used[k] = 0; 64 | d = 1; 65 | cycle[0] = i; 66 | DFS2(i, j); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /chapter05/artic.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 7; 8 | /* Матрица на съседство на графа */ 9 | char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0, 0, 0 }, 11 | { 1, 0, 1, 0, 0, 1, 0 }, 12 | { 0, 1, 0, 1, 0, 1, 0 }, 13 | { 0, 0, 1, 0, 1, 1, 0 }, 14 | { 0, 0, 0, 1, 0, 0, 0 }, 15 | { 0, 1, 1, 1, 0, 0, 1 }, 16 | { 0, 0, 0, 0, 0, 1, 0 } 17 | }; 18 | 19 | unsigned prenum[MAXN], lowest[MAXN], cN; 20 | 21 | unsigned min(unsigned a, unsigned b) { return (a < b) ? a : b; } 22 | 23 | void DFS(unsigned i) 24 | { unsigned j; 25 | prenum[i] = ++cN; 26 | for (j = 0; j < n; j++) 27 | if (A[i][j] && !prenum[j]) { 28 | A[i][j] = 2; /* строим покриващо дърво T */ 29 | DFS(j); 30 | } 31 | } 32 | 33 | /* Обхождане на дървото в postorder */ 34 | void postOrder(unsigned i) 35 | { unsigned j; 36 | for (j = 0; j < n; j++) 37 | if (2 == A[i][j]) postOrder(j); 38 | lowest[i] = prenum[i]; 39 | for (j = 0; j < n; j++) 40 | if (1 == A[i][j]) lowest[i] = min(lowest[i], prenum[j]); 41 | for (j = 0; j < n; j++) 42 | if (2 == A[i][j]) lowest[i] = min(lowest[i], lowest[j]); 43 | } 44 | 45 | void findArticPoints(void) 46 | { unsigned artPoints[MAXN], i, j, count; 47 | for (i = 0; i < n; i++) { 48 | prenum[i] = 0; lowest[i] = 0; artPoints[i] = 0; 49 | } 50 | cN = 0; 51 | DFS(0); 52 | for (i = 0; i < n; i++) 53 | if (0 == prenum[i]) { 54 | printf("Графът не е свързан - \n"); 55 | return; 56 | } 57 | postOrder(0); 58 | /* проверяваме 3.1) */ 59 | count = 0; 60 | for (i = 0; i < n; i++) 61 | if (2 == A[0][i]) count++; 62 | if (count > 1) artPoints[0] = 1; 63 | /* прилагаме стъпка 2) */ 64 | for (i = 1; i < n; i++) { 65 | for (j = 0; j < n; j++) 66 | if (2 == A[i][j] && lowest[j] >= prenum[i]) break; 67 | if (j < n) artPoints[i] = 1; 68 | } 69 | printf("Разделящите точки в графа са:\n"); 70 | for (i = 0; i < n; i++) 71 | if (artPoints[i]) printf("%u ", i + 1); 72 | printf("\n"); 73 | } 74 | 75 | int main(void) { 76 | findArticPoints(); 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /chapter05/belman.c: -------------------------------------------------------------------------------- 1 | for (k = 1; k <= n - 2; k++) /* повтаряме (n-2) пъти */ 2 | for (i = 0; i < n; i++) 3 | for (j = 0; j < n; j++) 4 | if (D[i] > D[j] + A[j][i]) 5 | D[i] = D[j] + A[j][i]; 6 | 7 | 8 | -------------------------------------------------------------------------------- /chapter05/bfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 14; 8 | /* Обхождане в ширина с начало връх v */ 9 | const unsigned v = 5; 10 | /* Матрица на съседство на графа */ 11 | const char A[MAXN][MAXN] = { 12 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13 | {1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14 | {0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 15 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 16 | {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 17 | {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, 18 | {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0}, 19 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 20 | {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1}, 21 | {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, 22 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 23 | {0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 24 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, 25 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0} 26 | }; 27 | 28 | char used[MAXN]; 29 | 30 | /* Функция за обхождане в ширина от даден връх */ 31 | void BFS(unsigned i) 32 | { unsigned k, j, p, queue[MAXN], currentVert, levelVertex, queueEnd; 33 | for (k = 0; k < n; k++) queue[k] = 0; 34 | for (k = 0; k < n; k++) used[k] = 0; 35 | queue[0] = i; used[i] = 1; 36 | currentVert = 0; levelVertex = 1; queueEnd = 1; 37 | while (currentVert < queueEnd) { /* докато опашката не е празна */ 38 | for (p = currentVert; p < levelVertex; p++) { 39 | /* p – взимаме поредния елемент от опашката */ 40 | printf("%u ", queue[p]+1); 41 | currentVert++; 42 | 43 | /* за всеки необходен наследник j на queue[p] */ 44 | for (j = 0; j < n; j++) 45 | if (A[queue[p]][j] && !used[j]) { 46 | queue[queueEnd++] = j; 47 | used[j] = 1; 48 | } 49 | } 50 | printf("\n"); 51 | levelVertex = queueEnd; 52 | } 53 | } 54 | 55 | int main(void) { 56 | printf("Обхождане в ширина от връх %u: \n", v); 57 | BFS(v-1); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /chapter05/btdfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 14; 8 | const unsigned sv = 1; /* Начален връх */ 9 | const unsigned ev = 10; /* Краен връх */ 10 | 11 | /* Матрица на съседство на графа */ 12 | const char A[MAXN][MAXN] = { 13 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14 | {1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15 | {0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 16 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 17 | {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 18 | {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, 19 | {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0}, 20 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 21 | {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1}, 22 | {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, 23 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 24 | {0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 25 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, 26 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0} 27 | }; 28 | 29 | char used[MAXN]; 30 | unsigned path[MAXN], count; 31 | 32 | void printPath(void) 33 | { unsigned k; 34 | for (k = 0; k <= count; k++) printf("%u ", path[k] + 1); 35 | printf("\n"); 36 | } 37 | 38 | /* Намира всички прости пътища между връх i и връх j */ 39 | void allDFS(unsigned i, unsigned j) 40 | { unsigned k; 41 | if (i == j) { 42 | path[count] = j; 43 | printPath(); 44 | return; 45 | } 46 | 47 | /* маркиране на посетеният връх */ 48 | used[i] = 1; 49 | path[count++] = i; 50 | for (k = 0; k < n; k++) /* рекурсия за всички съседи на i */ 51 | if (A[i][k] && !used[k]) allDFS(k, j); 52 | /* връщане: размаркирване на посетеният връх */ 53 | used[i] = 0; count--; 54 | } 55 | 56 | int main(void) { 57 | unsigned k; 58 | for (k = 0; k < n; k++) used[k] = 0; 59 | count = 0; 60 | printf("Прости пътища между %u и %u: \n", sv, ev); 61 | allDFS(sv-1, ev-1); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /chapter05/company.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой компании (върхове в графа) */ 4 | #define MAXN 150 5 | 6 | /* Брой компании (върхове в графа) */ 7 | const unsigned n = 6; 8 | const unsigned m = 1; /* Tърсим кои компании контролира компания 1 */ 9 | 10 | /* Матрица на съседство на графа */ 11 | const unsigned A[MAXN][MAXN] = { 12 | { 0, 8, 40, 20, 55, 20 }, 13 | { 0, 0, 0, 0, 0, 25 }, 14 | { 0, 0, 0, 0, 0, 10 }, 15 | { 0, 45, 0, 0, 0, 0 }, 16 | { 0, 0, 0, 31, 0, 0 }, 17 | { 0, 0, 0, 0, 0, 0 } 18 | }; 19 | 20 | unsigned control[MAXN]; 21 | char used[MAXN]; 22 | 23 | void addControls(void) 24 | { unsigned i, j; 25 | for (i = 0; i < n; i++) 26 | /* ако компания i е под контрол, прибавяме нейните “акции” към тези на m */ 27 | if (control[i] > 50 && !used[i]) { 28 | for (j = 0; j < n; j++) control[j] += A[i][j]; 29 | used[i] = 1; 30 | } 31 | } 32 | 33 | void solve(void) 34 | { unsigned i; 35 | for (i = 0; i < n; i++) { 36 | control[i] = 0; 37 | used[i] = 0; 38 | } 39 | for (i = 0; i < n; i++) control[i] = A[m-1][i]; 40 | for (i = 0; i < n; i++) addControls(); 41 | } 42 | 43 | void printResult(void) { 44 | unsigned i; 45 | printf("Компания %d контролира следните компании: \n", m); 46 | for (i = 0; i < n; i++) 47 | if (control[i] > 50) printf("%u: %3u% \n", i, control[i]); 48 | printf("\n"); 49 | } 50 | 51 | void main(void) { 52 | solve(); 53 | printResult(); 54 | } 55 | -------------------------------------------------------------------------------- /chapter05/dfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 14; 8 | /* Обхождане в дълбочина с начало връх v */ 9 | const unsigned v = 5; 10 | /* Матрица на съседство на графа */ 11 | const char A[MAXN][MAXN] = { 12 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13 | {1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14 | {0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 15 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 16 | {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 17 | {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, 18 | {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0}, 19 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 20 | {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1}, 21 | {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, 22 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 23 | {0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 24 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, 25 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0} 26 | }; 27 | 28 | char used[MAXN]; 29 | 30 | /* Обхождане в дълбочина от даден връх */ 31 | void DFS(unsigned i) 32 | { unsigned k; 33 | used[i] = 1; 34 | printf("%u ", i+1); 35 | for (k = 0; k < n; k++) 36 | if (A[i][k] && !used[k]) DFS(k); 37 | } 38 | 39 | int main(void) { 40 | unsigned k; 41 | for (k = 1; k < n; k++) used[k] = 0; 42 | printf("Обхождане в дълбочина от връх %u: \n", v); 43 | DFS(v-1); 44 | printf("\n"); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /chapter05/euler.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 100 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 8; 8 | /* Матрица на съседство на графа */ 9 | char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0, 0, 0, 0 }, 11 | { 0, 0, 1, 0, 1, 0, 0, 0 }, 12 | { 0, 0, 0, 1, 1, 0, 1, 0 }, 13 | { 0, 1, 0, 0, 0, 0, 0, 0 }, 14 | { 0, 0, 1, 0, 0, 1, 0, 0 }, 15 | { 0, 0, 1, 0, 0, 0, 0, 0 }, 16 | { 0, 0, 0, 0, 0, 0, 0, 1 }, 17 | { 1, 0, 0, 0, 0, 0, 0, 0 } 18 | }; 19 | 20 | /* Проверява дали е възможно да има Ойлеров цикъл (по теоремата на Ойлер) */ 21 | char isEulerGraph(void) 22 | { unsigned i, j; 23 | for (i = 0; i < n; i++) { 24 | int din = 0, dout = 0; 25 | for (j = 0; j < n; j++) { 26 | if (A[i][j]) din++; 27 | if (A[j][i]) dout++; 28 | } 29 | if (din != dout) return 0; 30 | } 31 | return 1; 32 | } 33 | 34 | /* Намира Ойлеров цикъл */ 35 | void findEuler(int i) 36 | { unsigned cStack[MAXN * MAXN], stack[MAXN * MAXN]; 37 | unsigned k, j, cTop = 0, sTop = 1; 38 | stack[sTop] = i; 39 | while (sTop > 0) { 40 | i = stack[sTop]; 41 | for (j = 0; j < n; j++) 42 | if (A[i][j]) { 43 | A[i][j] = 0; i = j; 44 | break; 45 | } 46 | if (j < n) 47 | stack[++sTop] = i; 48 | else 49 | cStack[++cTop] = stack[sTop--]; 50 | } 51 | printf("Ойлеровият цикъл е: "); 52 | for (k = cTop; k > 0; k--) { 53 | printf("%u ", cStack[k] + 1); 54 | } 55 | printf("\n"); 56 | } 57 | 58 | int main(void) { 59 | if (isEulerGraph()) findEuler(0); 60 | else 61 | printf("Графът не е Ойлеров!"); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /chapter05/floyd.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 10; 8 | /* Матрица на теглата на графа */ 9 | int A[MAXN][MAXN] = { 10 | { 0, 23, 0, 0, 0, 0, 0, 8, 0, 0 }, 11 | { 0, 0, 0, 3, 0, 0, 34, 0, 0, 0 }, 12 | { 0, 0, 0, 0, 0, 0, 0, 25, 0, 0 }, 13 | { 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }, 14 | { 0, 0, 0, 0, 0, 10, 0, 0, 0, 0 }, 15 | { 0, 0, 0, 0, 12, 0, 0, 0, 0, 0 }, 16 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 17 | { 0, 0, 25, 0, 0, 0, 0, 0, 0, 30 }, 18 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 19 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 20 | }; 21 | 22 | const int MAX_VALUE = 10000; 23 | 24 | /* Намира дължината на минималния път между всяка двойка върхове */ 25 | void floyd(void) 26 | { unsigned i, j, k; 27 | /* стойностите 0 се променят на MAX_VALUE */ 28 | for (i = 0; i < n; i++) 29 | for (j = 0; j < n; j++) 30 | if (0 == A[i][j]) A[i][j] = MAX_VALUE; 31 | /* Алгоритъм на Флойд */ 32 | for (k = 0; k < n; k++) 33 | for (i = 0; i < n; i++) 34 | for (j = 0; j < n; j++) 35 | if (A[i][j] > (A[i][k] + A[k][j])) 36 | A[i][j] = A[i][k] + A[k][j]; 37 | 38 | for (i = 0; i < n; i++) A[i][i] = 0; 39 | } 40 | 41 | void printMinPaths(void) 42 | { unsigned i, j; 43 | printf("Матрицата на теглата след изпълнението на алгоритъма на Флойд: \n"); 44 | for (i = 0; i < n; i++) { 45 | for (j = 0; j < n; j++) 46 | printf("%3d ", (MAX_VALUE == A[i][j]) ? 0 : A[i][j]); 47 | printf("\n"); 48 | } 49 | 50 | } 51 | 52 | int main(void) { 53 | floyd(); 54 | printMinPaths(); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /chapter05/fordfulk.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 100 5 | 6 | const unsigned n = 10; /* Брой върхове в графа */ 7 | const unsigned s = 1; /* Връх източник */ 8 | const unsigned t = 6; /* Връх консуматор */ 9 | /* Матрица на теглата на графа */ 10 | int A[MAXN][MAXN] = { 11 | { 0, 5, 5, 10, 0, 0 }, 12 | { 0, 0, 4, 0, 0, 5 }, 13 | { 0, 9, 0, 0, 7, 0 }, 14 | { 0, 0, 0, 0, 0, 7 }, 15 | { 0, 0, 0, 0, 0, 8 }, 16 | { 0, 0, 0, 0, 0, 0 } 17 | }; 18 | 19 | const int MAX_VALUE = 10000; 20 | 21 | int F[MAXN][MAXN]; 22 | unsigned path[MAXN]; 23 | char used[MAXN], found; 24 | 25 | void updateFlow(unsigned pl) 26 | { int incFlow = MAX_VALUE; 27 | unsigned i; 28 | for (i = 0; i < pl; i++) { 29 | unsigned p1 = path[i]; 30 | unsigned p2 = path[i + 1]; 31 | if (incFlow > A[p1][p2]) incFlow = A[p1][p2]; 32 | } 33 | for (i = 0; i < pl; i++) { 34 | unsigned p1 = path[i]; 35 | unsigned p2 = path[i + 1]; 36 | F[p1][p2] += incFlow; 37 | F[p2][p1] -= incFlow; 38 | A[p1][p2] -= incFlow; 39 | A[p2][p1] += incFlow; 40 | } 41 | } 42 | 43 | void DFS(unsigned i, unsigned level) 44 | { unsigned k; 45 | if (found) return; 46 | if (i == t-1) { 47 | found = 1; 48 | updateFlow(level - 1); 49 | } 50 | else 51 | for (k = 0; k < n; k++) 52 | if (!used[k] && A[i][k] > 0) { 53 | used[k] = 1; 54 | path[level] = k; 55 | DFS(k, level + 1); 56 | if (found) return; 57 | } 58 | } 59 | 60 | int main(void) { 61 | unsigned i, j; 62 | int flow; 63 | 64 | /* 1) инициализира се празен поток */ 65 | for (i = 0; i < n; i++) 66 | for (j = 0; j < n; j++) F[i][j] = 0; 67 | 68 | /* 2) намира увеличаващ път, докато е възможно */ 69 | do { 70 | for (i = 0; i < n; i++) used[i] = 0; 71 | found = 0; 72 | used[s-1] = 1; 73 | path[0] = s-1; 74 | DFS(s-1, 1); 75 | } while (found); 76 | 77 | /* Отпечатва потока */ 78 | printf("Максимален поток през графа : \n"); 79 | for (i = 0; i < n; i++) { 80 | for (j = 0; j < n; j++) printf("%4d", F[i][j]); 81 | printf("\n"); 82 | } 83 | 84 | printf("\n"); 85 | 86 | flow = 0; 87 | for (i = 0; i < n; i++) flow += F[i][t-1]; 88 | printf("С големина : %d\n", flow); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /chapter05/formcycl.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 14; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11 | {1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12 | {0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 13 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 14 | {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 15 | {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, 16 | {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0}, 17 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 18 | {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1}, 19 | {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, 20 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 21 | {0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 22 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, 23 | {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0} 24 | }; 25 | 26 | char used[MAXN], cycl; 27 | 28 | /* модифициран Depth-First-Search */ 29 | void DFS(unsigned i, int parent) 30 | { unsigned k; 31 | used[i] = 1; 32 | for (k = 0; k < n; k++) { 33 | if (cycl) return; 34 | if (A[i][k]) { 35 | if (used[k] && k != parent) { 36 | printf("Графът е цикличен! \n"); 37 | cycl = 1; 38 | return; 39 | } 40 | else if (k != parent) 41 | DFS(k, i); 42 | } 43 | } 44 | } 45 | 46 | int main(void) { 47 | unsigned k, i; 48 | for (k = 0; k < n; k++) used[k] = 0; 49 | cycl = 0; 50 | for (i = 0; i < n; i++) { 51 | if (!used[i]) DFS(i, -1); 52 | if (cycl) break; 53 | } 54 | if (0 == cycl) printf(" Графът е дърво (не съдържа цикли)!\n"); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /chapter05/kruskal.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Максимален брой ребра в графа */ 7 | #define MAXM 2000 8 | 9 | const unsigned n = 9; /* Брой върхове в графа */ 10 | const unsigned m = 14; /* Брой на ребрата в графа */ 11 | 12 | typedef struct { 13 | unsigned i, j; 14 | int f; 15 | } arc; 16 | 17 | arc S[MAXM] = { /* Списък от ребрата на графа и техните тегла */ 18 | { 1, 2, 1 }, 19 | { 1, 4, 2 }, 20 | { 2, 3, 3 }, 21 | { 2, 5, 13 }, 22 | { 3, 4, 4 }, 23 | { 3, 6, 3 }, 24 | { 4, 6, 16 }, 25 | { 4, 7, 14 }, 26 | { 5, 6, 12 }, 27 | { 5, 8, 1 }, 28 | { 5, 9, 13 }, 29 | { 6, 7, 1 }, 30 | { 6, 9, 1 } 31 | }; 32 | 33 | int prev[MAXN + 1]; 34 | 35 | int getRoot(int i) 36 | { int root, savei; 37 | /* намиране на корена на дървото */ 38 | root = i; 39 | while (-1 != prev[root]) root = prev[root]; 40 | /* свиване на пътя */ 41 | while (i != root) { 42 | savei = i; 43 | i = prev[i]; 44 | prev[savei] = root; 45 | } 46 | return root; 47 | } 48 | 49 | void kruskal(void) 50 | { int MST = 0; 51 | unsigned i, j; 52 | /* сортира списъка с ребрата в нарастващ ред по тяхното тегло */ 53 | quickSort(A, 0, M); 54 | 55 | printf("Ето ребрата, които участват в минималното покриващо дърво:\n"); 56 | for (i = 0; i < m; i++) { 57 | int r1 = getRoot(S[i].i); 58 | int r2 = getRoot(S[i].j); 59 | if (r1 != r2) { 60 | printf("(%u,%u) ", S[i].i, S[i].j); 61 | MST += S[i].f; 62 | prev[r2] = r1; 63 | } 64 | } 65 | printf("\nЦената на минималното покриващо дърво е %d.\n", MST); 66 | } 67 | 68 | int main(void) { 69 | unsigned i; 70 | for (i = 0; i < n + 1; i++) prev[i] = -1; 71 | kruskal(); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /chapter05/longpath.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 6; 8 | /* Матрица на теглата на графа */ 9 | const unsigned A[MAXN][MAXN] = { 10 | { 0, 12, 0, 0, 0, 0 }, 11 | { 0, 0, 40, 0, 17, 0 }, 12 | { 0, 0, 0, 0, 0, 0 }, 13 | { 0, 0, 0, 0, 30, 0 }, 14 | { 0, 0, 0, 0, 0, 20 }, 15 | { 0, 0, 20, 0, 0, 0 } 16 | }; 17 | 18 | int savePath[MAXN], maxDist[MAXN]; 19 | 20 | void DFS(unsigned i) 21 | { int max, d; 22 | unsigned j; 23 | if (maxDist[i] > 0) return; 24 | max = maxDist[i]; 25 | for (j = 0; j < n; j++) 26 | if (A[i][j]) { 27 | DFS(j); 28 | d = maxDist[j] + A[i][j]; 29 | if (d > max) { 30 | max = d; 31 | savePath[i] = j; 32 | } 33 | } 34 | 35 | maxDist[i] = max; 36 | } 37 | 38 | void solve(void) 39 | { unsigned i, maxi; 40 | /* инициализация */ 41 | for (i = 0; i < n; i++) { 42 | maxDist[i] = 0; 43 | savePath[i] = -1; 44 | } 45 | 46 | for (i = 0; i < n; i++) 47 | if (maxDist[i] == 0) DFS(i); 48 | 49 | maxi = 0; 50 | for (i = 0; i < n; i++) 51 | if (maxDist[i] > maxDist[maxi]) maxi = i; 52 | 53 | printf("Дължината на критичния път е %d\nПътят е: ", maxDist[maxi]); 54 | while (savePath[maxi] >= 0) { 55 | printf("%d ", maxi + 1); 56 | maxi = savePath[maxi]; 57 | } 58 | 59 | printf("%u\n", maxi + 1); 60 | } 61 | 62 | int main(void) { 63 | solve(); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /chapter05/maxindep.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 8; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0, 1, 0, 1 }, 11 | { 1, 0, 1, 0, 0, 1, 0, 0 }, 12 | { 0, 1, 0, 1, 1, 0, 0, 0 }, 13 | { 0, 0, 1, 0, 1, 0, 1, 0 }, 14 | { 0, 0, 1, 1, 0, 1, 0, 0 }, 15 | { 1, 1, 0, 0, 1, 0, 1, 1 }, 16 | { 0, 0, 0, 1, 0, 1, 0, 0 }, 17 | { 1, 0, 0, 0, 0, 1, 0, 0 } 18 | }; 19 | 20 | unsigned S[MAXN], T[MAXN], sN, tN; 21 | 22 | void print(void) 23 | { unsigned i; 24 | printf("{ "); 25 | for (i = 0; i < n; i++) 26 | if (T[i]) printf("%u ", i + 1); 27 | printf("} \n"); 28 | } 29 | 30 | void maxSubSet(unsigned last) 31 | { unsigned i, j; 32 | if (sN + tN == n) { 33 | print(); /* SuT=V -> отпечатва се решението */ 34 | return; 35 | } 36 | for (i = last; i < n; i++) { 37 | if (!S[i] && !T[i]) { 38 | for (j = 0; j < n; j++) 39 | if (A[i][j] && !S[j]) { 40 | S[j] = last+1; sN++; 41 | } 42 | T[i] = 1; tN++; 43 | maxSubSet(i+1); /* рекурсия */ 44 | T[i] = 0; tN--; 45 | for (j = 0; j < n; j++) 46 | if (S[j] == last+1) { S[j] = 0; sN--; } 47 | } 48 | } 49 | } 50 | 51 | void main(void) { 52 | unsigned i; 53 | printf("Ето всички максимални независими множества в графа:\n"); 54 | sN = tN = 0; 55 | for (i = 0; i < n; i++) S[i] = T[i] = 0; 56 | maxSubSet(0); 57 | } 58 | -------------------------------------------------------------------------------- /chapter05/mindom.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 6; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 1, 1, 0, 1, 0 }, 11 | { 0, 0, 0, 1, 0, 0 }, 12 | { 0, 0, 0, 1, 0, 0 }, 13 | { 0, 0, 0, 0, 0, 1 }, 14 | { 0, 1, 0, 0, 0, 0 }, 15 | { 1, 0, 0, 0, 0, 0 } 16 | }; 17 | 18 | unsigned cover[MAXN]; 19 | char T[MAXN]; 20 | 21 | void printSet(void) 22 | { unsigned i; 23 | printf("{ "); 24 | for (i = 0; i < n; i++) 25 | if (T[i]) printf("%u ", i + 1); 26 | printf("}\n"); 27 | } 28 | 29 | char ok(void) 30 | { unsigned i, j; 31 | for (i = 0; i < n; i++) if (T[i]) { 32 | /* проверка дали покритието се запазва при премахване на връх i */ 33 | if (0 == cover[i]) continue; 34 | for (j = 0; j < n; j++) if (cover[j]) { 35 | if (!(cover[j] - A[i][j]) && !T[j]) break; /* съществува връх, който остава непокрит */ 36 | } 37 | if (j == n) return 0; 38 | } 39 | return 1; 40 | } 41 | 42 | void findMinDom(unsigned last) 43 | { unsigned i, j; 44 | /* проверява се дали е намерено решение */ 45 | for (i = 0; i < n; i++) 46 | if (!cover[i] && !T[i]) break; 47 | if (i == n) { printSet(); return; } 48 | /* не - продължаваме да конструираме доминиращото множество */ 49 | for (i = last; i < n; i++) { 50 | T[i] = 1; 51 | for (j = 0; j < n; j++) if (A[i][j]) cover[j]++; 52 | if (ok()) findMinDom(i + 1); 53 | for (j = 0; j < n; j++) if (A[i][j]) cover[j]--; 54 | T[i] = 0; 55 | } 56 | } 57 | 58 | void main(void) 59 | { unsigned i; 60 | printf("Минималните доминиращи множества в графа са: \n"); 61 | for (i = 0; i < n; i++) { cover[i] = 0; T[i] = 0; } 62 | findMinDom(0); 63 | } 64 | -------------------------------------------------------------------------------- /chapter05/prim.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 9; 8 | /* Матрица на теглата на графа */ 9 | const int A[MAXN][MAXN] = { 10 | { 0, 1, 0, 2, 0, 0, 0, 0, 0 }, 11 | { 1, 0, 3, 0, 13, 0, 0, 0, 0 }, 12 | { 0, 3, 0, 4, 0, 3, 0, 0, 0 }, 13 | { 2, 0, 4, 0, 0, 16, 14, 0, 0 }, 14 | { 0, 13, 0, 0, 0, 12, 0, 1, 13 }, 15 | { 0, 0, 3, 16, 12, 0, 1, 0, 1 }, 16 | { 0, 0, 0, 14, 0, 1, 0, 0, 0 }, 17 | { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, 18 | { 0, 0, 0, 0, 13, 1, 0, 0, 0 } 19 | }; 20 | 21 | const int MAX_VALUE = 10000; 22 | 23 | char used[MAXN]; 24 | unsigned prev[MAXN]; 25 | int T[MAXN]; 26 | 27 | void prim(void) 28 | { int MST = 0; /* в променливата ще натрупваме цената на минималното покриващо дърво */ 29 | unsigned i, k; 30 | /* инициализация */ 31 | for (i = 0; i < n; i++) { used[i] = 0; prev[i] = 0; } 32 | used[0] = 1; /* избираме произволен начален връх */ 33 | for (i = 0; i < n; i++) 34 | T[i] = (A[0][i]) ? A[0][i] : MAX_VALUE; 35 | for (k = 0; k < n - 1; k++) { 36 | /* търсене на следващо минимално ребро */ 37 | int minDist = MAX_VALUE, j = -1; 38 | for (i = 0; i < n; i++) 39 | if (!used[i]) 40 | if (T[i] < minDist) { 41 | minDist = T[i]; 42 | j = i; 43 | } 44 | used[j] = 1; 45 | printf("(%u,%u) ", prev[j] + 1, j + 1); 46 | MST += minDist; 47 | for (i = 0; i < n; i++) 48 | if (!used[i] && A[j][i]) { 49 | if (T[i] > A[j][i]) { 50 | T[i] = A[j][i]; 51 | /* запазване на предшественика, за евентуално отпечатване на следващо минимално ребро */ 52 | prev[i] = j; 53 | } 54 | } 55 | } 56 | 57 | printf("\nЦената на минималното покриващо дърво е %d.\n", MST); 58 | printf("\n"); 59 | } 60 | 61 | int main(void) { 62 | prim(); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /chapter05/strcon1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 6; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 1, 1, 0, 0, 0 }, 11 | { 1, 0, 1, 0, 0, 0 }, 12 | { 1, 1, 0, 0, 0, 0 }, 13 | { 0, 0, 0, 0, 1, 1 }, 14 | { 0, 0, 0, 1, 0, 1 }, 15 | { 0, 0, 0, 1, 1, 0 } 16 | }; 17 | 18 | char used[MAXN]; 19 | 20 | /* модифицирано DFS */ 21 | void DFS(unsigned i) 22 | { unsigned k; 23 | used[i] = 1; 24 | printf("%u ", i + 1); 25 | for (k = 0; k < n; k++) 26 | if (A[i][k] && !used[k]) DFS(k); 27 | } 28 | 29 | int main(void) { 30 | unsigned i, comp; 31 | /* инициализация */ 32 | for (i = 0; i < n; i++) used[i] = 0; 33 | printf("\nЕто всички компоненти на свързаност: \n"); 34 | comp = 0; 35 | for (i = 0; i < n; i++) 36 | if (!used[i]) { 37 | comp++; 38 | printf("{ "); 39 | DFS(i); 40 | printf("}\n"); 41 | } 42 | if (1 == comp) 43 | printf("Графът е звързан.\n"); 44 | else 45 | printf("Брой на свързаните компоненти в графа: %d \n", comp); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /chapter05/strconn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 10; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 11 | { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, 12 | { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 13 | { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0 }, 14 | { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, 15 | { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, 16 | { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, 17 | { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, 18 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 19 | { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 } 20 | }; 21 | 22 | char used[MAXN]; 23 | unsigned postnum[MAXN], count = 0; 24 | 25 | /* Обхождане в дълбочина със запазване на номерацията */ 26 | void DFS(unsigned i) 27 | { unsigned j; 28 | used[i] = 1; 29 | for (j = 0; j < n; j++) 30 | if (!used[j] && A[i][j]) DFS(j); 31 | postnum[i] = count++; 32 | } 33 | 34 | /* Обхождане в дълбочина на графа G’ */ 35 | void backDFS(unsigned i) 36 | { unsigned j; 37 | printf("%u ", i + 1); 38 | count++; used[i] = 1; 39 | for (j = 0; j < n; j++) 40 | if (!used[j] && A[j][i]) backDFS(j); 41 | } 42 | 43 | /* Намира силно свързаните компоненти на графа */ 44 | void strongComponents(void) 45 | { unsigned i; 46 | for (i = 0; i < n; i++) used[i] = 0; 47 | while (count < n - 1) { 48 | for (i = 0; i < n; i++) 49 | if (!used[i]) DFS(i); 50 | } 51 | for (i = 0; i < n; i++) used[i] = 0; 52 | count = 0; 53 | while (count < n - 1) { 54 | unsigned max = 0, maxv = 0; 55 | for (i = 0; i < n; i++) 56 | if (!used[i] && postnum[i] > max) { 57 | max = postnum[i]; 58 | maxv = i; 59 | } 60 | printf("{ "); 61 | backDFS(maxv); 62 | printf("}\n"); 63 | } 64 | } 65 | 66 | int main(void) { 67 | printf("Силно свързаните компоненти в графа са:\n"); 68 | strongComponents(); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /chapter05/topsort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 5; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0 }, 11 | { 0, 0, 1, 0, 1 }, 12 | { 0, 0, 0, 1, 0 }, 13 | { 0, 0, 0, 0, 0 }, 14 | { 0, 0, 1, 0, 0 } 15 | }; 16 | 17 | char used[MAXN]; 18 | 19 | /* модифицирано DFS */ 20 | void DFS(unsigned i) 21 | { unsigned k; 22 | used[i] = 1; 23 | for (k = 0; k < n; k++) 24 | if (A[i][k] && !used[k]) DFS(k); 25 | printf("%u ", i + 1); 26 | } 27 | 28 | int main(void) { 29 | unsigned i; 30 | /* инициализация */ 31 | for (i = 0; i < n; i++) used[i] = 0; 32 | printf("Топологично сортиране (в обратен ред): \n"); 33 | for (i = 0; i < n; i++) 34 | if (!used[i]) DFS(i); 35 | printf("\n"); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /chapter05/topsortf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 8; 8 | /* Матрица на съседство на графа */ 9 | char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 0, 0, 0, 0 }, 11 | { 0, 0, 1, 0, 0, 0, 1, 0 }, 12 | { 0, 0, 0, 1, 0, 0, 0, 0 }, 13 | { 0, 0, 0, 0, 0, 0, 0, 0 }, 14 | { 0, 0, 0, 0, 0, 0, 0, 1 }, 15 | { 0, 0, 0, 0, 1, 0, 0, 0 }, 16 | { 0, 0, 1, 0, 0, 0, 0, 0 }, 17 | { 0, 0, 0, 0, 0, 0, 0, 0 } 18 | }; 19 | 20 | char used[MAXN]; 21 | unsigned topsort[MAXN], total = 0; 22 | 23 | void printSort(void) 24 | { unsigned i; 25 | printf("Топологично сортиране номер %u: ", ++total); 26 | for (i = 0; i < n; i++) printf("%u ", topsort[i] + 1); 27 | printf("\n"); 28 | } 29 | 30 | void fullTopSort(unsigned count) 31 | { unsigned i, j, k, saved[MAXN]; 32 | 33 | if (count == n) { printSort(); return; } 34 | 35 | /* намира всички върхове без предшественик */ 36 | for (i = 0; i < n; i++) { 37 | if (!used[i]) { 38 | for (j = 0; j < n; j++) 39 | if (A[j][i]) break; 40 | if (j == n) { 41 | for (k = 0; k < n; k++) { 42 | saved[k] = A[i][k]; A[i][k] = 0; 43 | } 44 | used[i] = 1; 45 | topsort[count] = i; 46 | fullTopSort(count + 1); /* рекурсия */ 47 | used[i] = 0; 48 | for (k = 0; k < n; k++) A[i][k] = saved[k]; 49 | } 50 | } 51 | } 52 | } 53 | 54 | int main(void) { 55 | unsigned i; 56 | for (i = 0; i < n; i++) used[i] = 0; 57 | fullTopSort(0); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /chapter05/tsp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 150 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 6; 8 | /* Матрица на теглата на графа */ 9 | const int A[MAXN][MAXN] = { 10 | { 0, 5, 0, 0, 7, 7 }, 11 | { 5, 0, 5, 0, 0, 0 }, 12 | { 0, 5, 0, 6, 5, 0 }, 13 | { 0, 0, 6, 0, 3, 3 }, 14 | { 7, 0, 5, 3, 0, 5 }, 15 | { 7, 0, 0, 3, 5, 0 } 16 | }; 17 | 18 | const int MAX_VALUE = 10000; 19 | 20 | char used[MAXN]; 21 | unsigned minCycle[MAXN], cycle[MAXN]; 22 | int curSum, minSum; 23 | 24 | void printCycle(void) 25 | { unsigned i; 26 | printf("Минимален Хамилтонов цикъл: 1"); 27 | for (i = 0; i < n - 1; i++) printf(" %u", minCycle[i] + 1); 28 | printf(" 1, дължина %d\n", minSum); 29 | } 30 | 31 | /* Намира минимален Хамилтонов цикъл */ 32 | void hamilton(unsigned i, unsigned level) 33 | { unsigned k; 34 | if ((0 == i) && (level > 0)) { 35 | if (level == n) { 36 | minSum = curSum; 37 | for (k = 0; k < n; k++) minCycle[k] = cycle[k]; 38 | } 39 | return; 40 | } 41 | if (used[i]) return; 42 | used[i] = 1; 43 | for (k = 0; k < n; k++) 44 | if (A[i][k] && k != i) { 45 | cycle[level] = k; 46 | curSum += A[i][k]; 47 | if (curSum < minSum) /* прекъсване на генерирането */ 48 | hamilton(k, level + 1); 49 | curSum -= A[i][k]; 50 | } 51 | used[i] = 0; 52 | } 53 | 54 | int main(void) { 55 | unsigned k; 56 | for (k = 0; k < n; k++) used[k] = 0; 57 | minSum = MAX_VALUE; 58 | curSum = 0; 59 | cycle[0] = 1; 60 | hamilton(0, 0); 61 | printCycle(); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /chapter05/v-base.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 9; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 11 | { 1, 0, 1, 0, 0, 0, 0, 0, 0 }, 12 | { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 13 | { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, 14 | { 0, 0, 0, 0, 0, 1, 0, 0, 0 }, 15 | { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, 16 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 17 | { 1, 0, 0, 0, 0, 1, 0, 0, 0 }, 18 | { 0, 1, 0, 0, 0, 0, 0, 0, 0 } 19 | }; 20 | 21 | char used[MAXN], base[MAXN]; 22 | 23 | void DFS(unsigned i) 24 | { unsigned k; 25 | used[i] = 1; 26 | for (k = 0; k < n; k++) 27 | if (A[i][k] && !used[k]) { 28 | base[k] = 0; 29 | DFS(k); 30 | } 31 | } 32 | 33 | void solve(void) { 34 | unsigned i, j; 35 | for (i = 0; i < n; i++) base[i] = 1; 36 | for (i = 0; i < n; i++) 37 | if (base[i]) { 38 | for (j = 0; j < n; j++) used[j] = 0; 39 | DFS(i); 40 | } 41 | } 42 | 43 | void print() { 44 | unsigned i, count = 0; 45 | printf("Ето върховете, образуващи база в графа:\n"); 46 | for (i = 0; i < n; i++) 47 | if (base[i]) { printf("%u ", i + 1); count++; } 48 | printf("\nБрой на върховете в базата: %u\n", count); 49 | } 50 | 51 | int main(void) { 52 | solve(); 53 | print(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /chapter06/bagrec.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | const unsigned n = 10; 5 | const float M = 10.5; 6 | const float c[MAXN] = { 10.3, 9.0, 12.0, 8.0, 4.0, 8.4, 9.1, 17.0, 6.0, 9.7 }; 7 | const float m[MAXN] = { 4.0, 2.6, 3.0, 5.3, 6.4, 2.0, 4.0, 5.1, 3.0, 4.0 }; 8 | 9 | unsigned taken[MAXN], saveTaken[MAXN], tn, sn; 10 | float VmaX, Vtemp, Ttemp, totalV; 11 | 12 | void generate(unsigned i) 13 | { unsigned k; 14 | if (Ttemp > M) return; 15 | if (Vtemp + totalV < VmaX) return; 16 | if (i == n) { 17 | if (Vtemp > VmaX) { /* запазване на оптималното решение */ 18 | VmaX = Vtemp; sn = tn; 19 | for (k = 0; k < tn; k++) saveTaken[k] = taken[k]; 20 | } 21 | return; 22 | } 23 | taken[tn++] = i; Vtemp += c[i]; totalV -= c[i]; Ttemp += m[i]; 24 | generate(i + 1); 25 | tn--; Vtemp -= c[i]; Ttemp -= m[i]; 26 | generate(i + 1); 27 | totalV += c[i]; 28 | } 29 | 30 | int main(void) { 31 | unsigned i; 32 | tn = 0; VmaX = 0; totalV = 0; 33 | for (i = 0; i < n; i++) totalV += c[i]; 34 | generate(0); 35 | printf("Максимално тегло: %.2f\nИзбрани предмети: \n", VmaX); 36 | for (i = 0; i < sn; i++) printf("%u ", saveTaken[i] + 1); 37 | printf("\n"); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /chapter06/bool.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой булеви променливи */ 4 | #define MAXN 100 5 | /* Максимален брой дизюнкти */ 6 | #define MAXK 100 7 | 8 | const unsigned n = 4; /* Брой на булевите променливи */ 9 | const unsigned k = 5; /* Брой на дизюнктите */ 10 | 11 | const int expr[][MAXK] = { 12 | { 1, 4 }, 13 | { -1, 2 }, 14 | { 1, -3 }, 15 | { -2, 3, -4 }, 16 | { -1, -2, -3 } 17 | }; 18 | 19 | int values[MAXN]; 20 | 21 | void printAssignment(void) 22 | { unsigned i; 23 | printf("Изразът е удовлетворим за: "); 24 | for (i = 0; i < n; i++) printf("X%u=%u ", i+1, values[i]); 25 | printf("\n"); 26 | } 27 | 28 | /* във всеки от к-те дизюнкта поне един литерал трябва да има стойност “истина” */ 29 | int true(void) 30 | { unsigned i; 31 | for (i = 0; i < k; i++) { 32 | unsigned j = 0; 33 | char ok = 0; 34 | while (expr[i][j] != 0) { 35 | int p = expr[i][j]; 36 | if ((p > 0) && (1 == values[p-1])) { ok = 1; break; } 37 | if ((p < 0) && (0 == values[-p-1])) { ok = 1; break; } 38 | j++; 39 | } 40 | if (!ok) return 0; 41 | } 42 | return 1; 43 | } 44 | 45 | /* присвоява стойности на променливите */ 46 | void assign(unsigned i) 47 | { if (i == n) { 48 | if (true()) printAssignment(); 49 | return; 50 | } 51 | values[i] = 1; assign(i + 1); 52 | values[i] = 0; assign(i + 1); 53 | } 54 | 55 | int main(void) { 56 | assign(0); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /chapter06/boolcut.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой булеви променливи */ 4 | #define MAXN 100 5 | /* Максимален брой дизюнкти */ 6 | #define MAXK 100 7 | 8 | const unsigned n = 4; /* Брой на булевите променливи */ 9 | const unsigned k = 5; /* Брой на дизюнктите */ 10 | 11 | const int expr[][MAXK] = { 12 | { 1, 4 }, 13 | { -1, 2 }, 14 | { 1, -3 }, 15 | { -2, 3, -4 }, 16 | { -1, -2, -3 } 17 | }; 18 | 19 | int values[MAXN]; 20 | 21 | void printAssign(void) 22 | { unsigned i; 23 | printf("Изразът е удовлетворим за: "); 24 | for (i = 0; i < n; i++) printf("X%d=%d ", i + 1, values[i]); 25 | printf("\n"); 26 | } 27 | 28 | /* във всеки от k-те дизюнкта поне един литерал трябва да има стойност “истина” */ 29 | int true(int t) 30 | { unsigned i; 31 | for (i = 0; i < k; i++) { 32 | unsigned j = 0; 33 | char ok = 0; 34 | while (expr[i][j] != 0) { 35 | int p = expr[i][j]; 36 | if ((p > t) || (-p > t)) { ok = 1; break; } 37 | if ((p > 0) && (1 == values[p-1])) { ok = 1; break; } 38 | if ((p < 0) && (0 == values[-p-1])) { ok = 1; break; } 39 | j++; 40 | } 41 | if (!ok) return 0; 42 | } 43 | return 1; 44 | } 45 | 46 | /* присвоява стойности на променливите */ 47 | void assign(unsigned i) 48 | { if (!true(i)) return; 49 | if (i == n) { 50 | printAssign(); 51 | return; 52 | } 53 | values[i] = 1; assign(i + 1); 54 | values[i] = 0; assign(i + 1); 55 | } 56 | 57 | int main(void) { 58 | assign(0); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /chapter06/colorm2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 5; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 1, 0, 0, 1 }, 11 | { 1, 0, 1, 1, 1 }, 12 | { 0, 1, 0, 1, 0 }, 13 | { 0, 1, 1, 0, 1 }, 14 | { 1, 1, 0, 1, 0 }}; 15 | 16 | unsigned col[MAXN], maxCol, count = 0; 17 | char foundSol = 0; 18 | 19 | void showSol(void) 20 | { unsigned i; 21 | count++; 22 | printf("Минимално оцветяване на графа: \n"); 23 | for (i = 0; i < n; i++) printf("Връх %u - с цвят %u \n", i + 1, col[i]); 24 | } 25 | 26 | void nextCol(unsigned i) 27 | { unsigned k, j, success; 28 | if (i == n) { showSol(); return; } 29 | for (k = 1; k <= maxCol; k++) { 30 | col[i] = k; 31 | success = 1; 32 | for (j = 0; j < n; j++) 33 | if (1 == A[i][j] && col[j] == col[i]) { 34 | success = 0; 35 | break; 36 | } 37 | if (success) nextCol(i + 1); 38 | col[i] = 0; 39 | } 40 | } 41 | 42 | int main(void) { 43 | unsigned i; 44 | for (maxCol = 1; maxCol <= n; maxCol++) { 45 | for (i = 0; i < n; i++) col[i] = 0; 46 | nextCol(0); 47 | if (count) break; 48 | } 49 | printf("Общ брой намерени оцветявания с %u цвята: %u \n", maxCol, count); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /chapter06/knight.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Максимален размер на дъската */ 5 | #define MAXN 10 6 | /* Максимален брой правила за движение на коня */ 7 | #define MAXD 10 8 | 9 | /* Размер на дъската */ 10 | const unsigned n = 6; 11 | /* Стартова позиция */ 12 | const unsigned startX = 1; 13 | const unsigned startY = 1; 14 | /* Правила за движение на коня */ 15 | const unsigned maxDiff = 8; 16 | const int diffX[MAXD] = { 1, 1, -1, -1, 2, -2, 2, -2 }; 17 | const int diffY[MAXD] = { 2, -2, 2, -2, 1, 1, -1, -1 }; 18 | 19 | unsigned board[MAXN][MAXN]; 20 | unsigned newX, newY; 21 | 22 | void printBoard(void) 23 | { unsigned i, j; 24 | for (i = n; i > 0; i--) { 25 | for (j = 0; j < n; j++) printf("%3u", board[i-1][j]); 26 | printf("\n"); 27 | } 28 | exit(0); /* изход от програмата */ 29 | } 30 | 31 | void nextMove(unsigned X, unsigned Y, unsigned i) 32 | { unsigned k; 33 | board[X][Y] = i; 34 | if (i == n * n) { printBoard(); return; } 35 | for (k = 0; k < maxDiff; k++) { 36 | newX = X + diffX[k]; newY = Y + diffY[k]; 37 | if ((newX >= 0 && newX < n && newY >= 0 && newY < n) && (0 == board[newX][newY])) 38 | nextMove(newX, newY, i + 1); 39 | } 40 | board[X][Y] = 0; 41 | } 42 | 43 | int main(void) { 44 | unsigned i, j; 45 | for (i = 0; i < n; i++) 46 | for (j = 0; j < n; j++) board[i][j] = 0; 47 | nextMove(startX-1, startY-1, 1); 48 | printf("Задачата няма решение. \n"); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /chapter06/longpath.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой върхове в графа */ 4 | #define MAXN 200 5 | 6 | /* Брой върхове в графа */ 7 | const unsigned n = 6; 8 | /* Матрица на съседство на графа */ 9 | const char A[MAXN][MAXN] = { 10 | { 0, 10, 0, 5, 0, 0 }, 11 | { 0, 0, 5, 0, 0, 15 }, 12 | { 0, 0, 0, 10, 5, 0 }, 13 | { 0, 10, 0, 0, 10, 0 }, 14 | { 0, 5, 0, 0, 0, 0 }, 15 | { 0, 0, 0, 0, 0, 0 }}; 16 | 17 | unsigned vertex[MAXN], savePath[MAXN]; 18 | char used[MAXN]; 19 | int maxLen, tempLen, si; 20 | 21 | void addVertex(unsigned i) 22 | { unsigned j, k; 23 | if (tempLen > maxLen) { /* намерили сме по-дълъг път => запазваме го */ 24 | maxLen = tempLen; 25 | for (j = 0; j < i; j++) savePath[j] = vertex[j]; 26 | si = i; 27 | } 28 | for (k = 0; k < n; k++) { 29 | if (!used[k]) { /* ако върхът k не участва в пътя до момента */ 30 | if (0 == i || A[vertex[i - 1]][k] > 0) { /* ако върхът, който добавяме, е съседен на последния от маршрута */ 31 | if (i > 0) tempLen += A[vertex[i - 1]][k]; 32 | used[k] = 1; /* маркираме k като участващ в пътя; */ 33 | vertex[i] = k; /* добавяме върха k към пътя; */ 34 | addVertex(i + 1); 35 | used[k] = 0; /* връщане от рекурсията */ 36 | if (i > 0) tempLen -= A[vertex[i - 1]][k]; 37 | } 38 | } 39 | } 40 | } 41 | 42 | int main(void) { 43 | unsigned i; 44 | maxLen = 0; tempLen = 0; si = 0; 45 | for (i = 0; i < n; i++) used[i] = 0; 46 | addVertex(0); 47 | printf("Най-дългият път е: \n"); 48 | for (i = 0; i < si; i++) printf("%u ", savePath[i] + 1); 49 | printf("\nс обща дължина %d\n", maxLen); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /chapter06/program.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Максимален брой учители */ 4 | #define MAXT 100 5 | /* Максимален брой класове */ 6 | #define MAXC 100 7 | 8 | /* Брой учители */ 9 | const unsigned t = 3; 10 | /* Брой класове */ 11 | const unsigned c = 4; 12 | unsigned cl[MAXC][MAXT] = { 13 | { 5, 5, 5 }, /* информация за клас 1 */ 14 | { 5, 5, 5 }, 15 | { 5, 0, 0 }, 16 | { 0, 0, 5 } /* информация за клас C */ 17 | }; 18 | 19 | const unsigned MAX_VALUE = 20000; 20 | 21 | char usedC[100][MAXC]; 22 | unsigned teach[MAXT], minimal; 23 | 24 | void generate(unsigned teacher, unsigned level, unsigned mX, unsigned totalHours) 25 | { unsigned i, j; 26 | if (totalHours >= minimal) return; 27 | if (teacher == t) { 28 | unsigned min = MAX_VALUE; 29 | for (i = 0; i < c; i++) 30 | for (j = 0; j < t; j++) 31 | if (cl[i][j] < min && 0 != cl[i][j]) min = cl[i][j]; 32 | if (min == MAX_VALUE) { 33 | if (totalHours < minimal) minimal = totalHours; 34 | } 35 | else { 36 | generate(0, level + 1, min, totalHours + min); 37 | } 38 | return; 39 | } 40 | 41 | /* определя клас за учителя teacher, с който той да проведе min часа */ 42 | for (i = 0; i < c; i++) { 43 | if (cl[i][teacher] > 0 && !usedC[level][i]) { 44 | cl[i][teacher] -= mX; 45 | usedC[level][i] = 1; 46 | generate(teacher + 1, level, mX, totalHours); 47 | usedC[level][i] = 0; /* връщане */ 48 | cl[i][teacher] += mX; 49 | } 50 | } 51 | 52 | /* Ако не е намерено присвояване за учителя, това означава, че не са му останали 53 | * часове за преподаване */ 54 | if (i == c) generate(teacher + 1, level, mX, totalHours); 55 | } 56 | 57 | int main(void) { 58 | unsigned i, j; 59 | for (i = 0; i < 100; i++) 60 | for (j = 0; j < c; j++) usedC[i][j] = 0; 61 | minimal = MAX_VALUE; 62 | generate(t, 0, 0, 0); 63 | printf("Минималното разписание е с продължителност %u часа.\n", minimal); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /chapter06/queens.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Максимален размер на дъската */ 5 | #define MAXN 100 6 | 7 | /* Размер на дъската */ 8 | const unsigned n = 13; 9 | 10 | unsigned col[MAXN] , RD[2*MAXN - 1], 11 | LD[2*MAXN], queens [MAXN]; 12 | 13 | /* Отпечатва намереното разположение на цариците */ 14 | void printBoard() 15 | { unsigned i , j ; 16 | for (i = 0; i < n; i++) { 17 | printf("\n"); 18 | for (j = 0; j < n; j++) 19 | if(queens[i] == j) printf("x "); 20 | else printf(". "); 21 | } 22 | printf("\n"); 23 | exit(0); 24 | } 25 | 26 | /* Намира следваща позиция за поставяне на царица */ 27 | void generate(unsigned i) 28 | { if(i == n) printBoard(); 29 | unsigned k; 30 | for (k = 0; k <= n; k++) { 31 | if (col[k] && RD[i + k] && LD[n + i - k]) { 32 | col[k] = 0; RD[i + k] = 0; LD[n + i - k] = 0; queens[i] = k; 33 | generate(i + 1); 34 | col[k] = 1; RD[i + k] = 1; LD[n + i - k] = 1; 35 | } 36 | } 37 | } 38 | 39 | int main(void) { 40 | unsigned i; 41 | for (i = 0; i < n; i++) col[i] = 1; 42 | for (i = 0; i < (2*n - 1); i++) RD[i] = 1; 43 | for (i = 0; i < 2*n; i++) LD[i] = 1; 44 | generate(0); 45 | printf("Задачата няма решение! \n"); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /chapter07/hanoy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const unsigned n = 4; 4 | 5 | void diskMove(unsigned n, char a, char b) 6 | { printf("Преместете диск %u от %c на %c.\n", n, a, b); } 7 | 8 | void hanoy(char a, char c, char b, unsigned numb) 9 | { if (1 == numb) 10 | diskMove(1, a, c); 11 | else { 12 | hanoy(a, b, c, numb - 1); 13 | diskMove(numb, a, c); 14 | hanoy(b, c, a, numb - 1); 15 | } 16 | } 17 | 18 | int main(void) { 19 | printf("Брой дискове: %u\n", n); 20 | hanoy('A', 'C', 'B', n); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /chapter07/heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | int m[MAX]; 5 | 6 | const unsigned n = 100; /* Брой елементи в масива */ 7 | const unsigned k = 10; /* Пореден номер на търсения елемент */ 8 | 9 | void init(int m[], unsigned n) /* Запълва масива със случайни числа */ 10 | { unsigned i; 11 | for (i = 0; i < n; i++) 12 | m[i] = rand() % (2*n + 1); 13 | } 14 | 15 | void siftMin(int l, int r) /* Отсяване на елемента от върха на пирамидата */ 16 | { int i,j; 17 | int x; 18 | i = l; j = i + i + 1; x = m[i]; 19 | while (j <= r) { 20 | if (j < r) 21 | if (m[j] > m[j+1]) 22 | j++; 23 | if (x <= m[j]) 24 | break; 25 | m[i] = m[j]; 26 | i = j; 27 | j = j*2 + 1; 28 | } 29 | m[i] = x; 30 | } 31 | 32 | void siftMax(int l, int r) /* Отсяване на елемента от върха на пирамидата */ 33 | { int i,j; 34 | int x; 35 | i = l; j = i + i + 1; x = m[i]; 36 | while (j <= r) { 37 | if (j < r) 38 | if (m[j] < m[j+1]) 39 | j++; 40 | if (x >= m[j]) 41 | break; 42 | m[i] = m[j]; 43 | i = j; 44 | j = j*2 + 1; 45 | } 46 | m[i] = x; 47 | } 48 | 49 | void heapFindK(unsigned k) /* Търсене на k-ия елемент с пирамида */ 50 | { int l,r; 51 | char useMax; 52 | if (useMax = (k > n/2)) 53 | k = n - k - 1; 54 | l = n/2; r = n - 1; 55 | /* Построяване на пирамидата */ 56 | while (l-- > 0) 57 | if (useMax) siftMax(l,r); else siftMin(l,r); 58 | /* (k-1)-кратно премахване на минималния елемент */ 59 | for (r = (int)n-1; r >= (int)(n-k); r--) { 60 | m[0] = m[r]; 61 | if (useMax) siftMax(0,r); else siftMin(0,r); 62 | } 63 | } 64 | 65 | void print(int m[], unsigned n) /* Извежда масива на екрана */ 66 | { unsigned i; 67 | for (i = 0; i < n; i++) 68 | printf("%8d", m[i]); 69 | } 70 | 71 | int main(void) { 72 | init(m,n); 73 | printf("Масивът преди търсенето:"); print(m,n); 74 | printf("\nТърсим k-ия елемент: k=%u", k); 75 | heapFindK(k); 76 | printf("\nk-ият елемент е: %d", m[0]); 77 | return 0; 78 | } -------------------------------------------------------------------------------- /chapter07/major1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | unsigned count(CDataType m[], unsigned size, CDataType candidate) 5 | { unsigned cnt, i; 6 | for (i = cnt = 0; i < size; i++) 7 | if (m[i] == candidate) 8 | cnt++; 9 | return cnt; 10 | } 11 | 12 | char findMajority(CDataType m[], unsigned size, CDataType *majority) 13 | { unsigned i, size2 = size / 2; 14 | for (i = 0; i < size; i++) 15 | if (count(m, size, m[i]) > size2) { 16 | *majority = m[i]; 17 | return 1; 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | int main(void) { 24 | CDataType majority; 25 | if (findMajority("AAACCBBCCCBCC", 13, &majority)) 26 | printf("Мажорант: %c\n", majority); 27 | else 28 | printf("Няма мажорант.\n"); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /chapter07/major10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | void findMajority(CDataType m[], unsigned size, CDataType *majority) 5 | { unsigned i, curCnt; 6 | do { 7 | for (curCnt = 0, i = 1; i < size; i += 2) 8 | if (m[i - 1] == m[i]) 9 | m[curCnt++] = m[i]; 10 | if (!(curCnt & 1)) 11 | m[curCnt++] = m[size - 1]; 12 | size = curCnt; 13 | } while (size > 1); 14 | *majority = m[0]; 15 | } 16 | 17 | int main(void) { 18 | CDataType m[14] = "AAACCBBCCCBCC"; 19 | CDataType majority; 20 | findMajority(m, 13, &majority); 21 | printf("Мажорант: %c\n", majority); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /chapter07/major11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define CDataType char 4 | 5 | void findMajority(CDataType m[], unsigned size, CDataType *majority) 6 | { unsigned i, curCnt; 7 | unsigned *cnt = (unsigned *) malloc(size * sizeof(*cnt)); 8 | for (i = 0; i < size; i++) cnt[i] = 1; 9 | do { 10 | for (curCnt = 0, i = 1; i < size; i += 2) { 11 | if (m[i - 1] == m[i]) { 12 | cnt[curCnt] = cnt[i - 1] + cnt[i]; 13 | m[curCnt++] = m[i]; 14 | } 15 | else if (cnt[i] > cnt[i - 1]) { 16 | cnt[curCnt] = cnt[i] - cnt[i - 1]; 17 | m[curCnt++] = m[i]; 18 | } 19 | else if (cnt[i] < cnt[i - 1]) { 20 | cnt[curCnt] = cnt[i - 1] - cnt[i]; 21 | m[curCnt++] = m[i - 1]; 22 | } 23 | } 24 | if (size & 1) { 25 | cnt[curCnt] = cnt[i - 1]; 26 | m[curCnt++] = m[i - 1]; 27 | } 28 | size = curCnt; 29 | } while (size > 1); 30 | free(cnt); 31 | *majority = m[0]; 32 | } 33 | 34 | int main() { 35 | CDataType m[14] = "AAACCBBCCCBCC"; 36 | CDataType majority; 37 | findMajority(m, 13, &majority); 38 | printf("Мажорант: %c\n", majority); 39 | return 0; 40 | } -------------------------------------------------------------------------------- /chapter07/major12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | /* Променливи, функции и дефиниции за работа със стек */ 5 | #define STACK_SIZE 100 6 | CDataType stack[STACK_SIZE]; 7 | unsigned stIndex; 8 | void stackInit(void) { stIndex = 0; } 9 | void stackPush(CDataType elem) { stack[stIndex++] = elem; } 10 | CDataType stackPop(void) { return stack[--stIndex]; } 11 | CDataType stackTop(void) { return stack[stIndex - 1]; } 12 | char stackIsEmpty(void) { return 0 == stIndex; } 13 | 14 | char findMajority(CDataType m[], unsigned size, CDataType *majority) 15 | { unsigned i, cnt; 16 | stackInit(); 17 | for (stackPush(m[0]), i = 1; i < size; i++) { 18 | if (stackIsEmpty()) 19 | stackPush(m[i]); 20 | else if (stackTop() == m[i]) 21 | stackPush(m[i]); 22 | else 23 | stackPop(); 24 | } 25 | if (stackIsEmpty()) return 0; 26 | for (*majority = stackPop(), i = cnt = 0; i < size; i++) 27 | if (m[i] == *majority) 28 | cnt++; 29 | return(cnt > size / 2); 30 | } 31 | 32 | int main() { 33 | CDataType majority; 34 | if (findMajority("AAACCBBCCCBCC", 13, &majority)) 35 | printf("Мажорант: %c\n", majority); 36 | else 37 | printf("Няма мажорант.\n"); 38 | return 0; 39 | } -------------------------------------------------------------------------------- /chapter07/major13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | char FindMajority(CDataType m[], unsigned size, CDataType *majority) 5 | { unsigned cnt, i; 6 | for (i = cnt = 0; i < size; i++) { 7 | if (0 == cnt) { 8 | *majority = m[i]; 9 | cnt = 1; 10 | } 11 | else if (m[i] == *majority) 12 | cnt++; 13 | else 14 | cnt--; 15 | } 16 | if (cnt > 0) { 17 | for (i = cnt = 0; i < size; i++) 18 | if (m[i] == *majority) 19 | cnt++; 20 | return(cnt > size / 2); 21 | } 22 | return 0; 23 | } 24 | 25 | int main() { 26 | CDataType majority; 27 | if (FindMajority("AAACCBBCCCBCC", 13, &majority)) 28 | printf("Мажорант: %c\n", majority); 29 | else 30 | printf("Няма мажорант.\n"); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /chapter07/major2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | char findMajority(CDataType m[], unsigned size, CDataType *majority) 5 | { unsigned i, j, cnt, size2 = size / 2; 6 | for (i = 0; i <= size / 2; i++) { 7 | for (cnt = 0, j = i; j < size; j++) 8 | if (m[i] == m[j]) cnt++; 9 | if (cnt > size2) { 10 | *majority = m[i]; 11 | return 1; 12 | } 13 | } 14 | return 0; 15 | } 16 | 17 | int main(void) { 18 | CDataType majority; 19 | if (findMajority("AAACCBBCCCBCC", 13, &majority)) 20 | printf("Мажорант: %c\n", majority); 21 | else 22 | printf("Няма мажорант.\n"); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /chapter07/major3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | char findMajority(CDataType m[], unsigned size, CDataType *majority) 5 | { unsigned i, j, cnt, size2 = size / 2; 6 | for (i = 0; i <= size / 2; i++) { 7 | for (cnt = 0, j = i; j < size; j++) 8 | if (cnt + size - j <= size2) 9 | break; 10 | else if (m[i] == m[j]) 11 | cnt++; 12 | if (cnt > size2) { 13 | *majority = m[i]; 14 | return 1; 15 | } 16 | } 17 | return 0; 18 | } 19 | 20 | int main(void) { 21 | CDataType majority; 22 | if (findMajority("AAACCBBCCCBCC", 13, &majority)) 23 | printf("Мажорант: %c\n", majority); 24 | else 25 | printf("Няма мажорант.\n"); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /chapter07/major6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX_NUM 127 3 | #define CDataType unsigned char 4 | CDataType cnt[MAX_NUM + 1]; 5 | 6 | char findMajority(CDataType m[], unsigned size, CDataType *majority) 7 | { unsigned i, j, size2 = size / 2; 8 | /* Инициализация */ 9 | for (i = 0; i < MAX_NUM; i++) 10 | cnt[i] = 0; 11 | /* Броене */ 12 | for (j = 0; j < size; j++) 13 | cnt[m[j]]++; 14 | /* Проверка за мажорант */ 15 | for (i = 0; i < MAX_NUM; i++) 16 | if (cnt[i] > size2) { 17 | *majority = i; 18 | return 1; 19 | } 20 | return 0; 21 | } 22 | 23 | int main(void) { 24 | CDataType majority; 25 | if (findMajority("AAACCBBCCCBCC", 13, &majority)) 26 | printf("Мажорант: %c\n", majority); 27 | else 28 | printf("Няма мажорант.\n"); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /chapter07/major7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | unsigned count(CDataType m[], unsigned left, unsigned right, CDataType candidate) 5 | { unsigned cnt; 6 | for (cnt = 0; left <= right; left++) 7 | if (m[left] == candidate) 8 | cnt++; 9 | return cnt; 10 | } 11 | 12 | char findMajority(CDataType m[], unsigned left, unsigned right, CDataType *majority) 13 | { unsigned mid; 14 | if (left == right) { 15 | *majority = m[left]; 16 | return 1; 17 | } 18 | mid = (left + right) / 2; 19 | if (findMajority(m, left, mid, majority)) 20 | if (count(m, left, right, *majority) > (right - left + 1) / 2) 21 | return 1; 22 | if (findMajority(m, mid + 1, right, majority)) 23 | if (count(m, left, right, *majority) > (right - left + 1) / 2) 24 | return 1; 25 | return 0; 26 | } 27 | 28 | int main(void) { 29 | CDataType majority; 30 | if (findMajority("AAACCBBCCCBCC", 0, 12, &majority)) 31 | printf("Мажорант: %c\n", majority); 32 | else 33 | printf("Няма мажорант.\n"); 34 | return 0; 35 | } -------------------------------------------------------------------------------- /chapter07/major8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | #define MAX 100 4 | 5 | void findMajority(CDataType m[], unsigned size, CDataType *majority) 6 | { unsigned i, curCnt; 7 | char part = 0; 8 | do { 9 | for (curCnt = 0, i = 1; i < size; i += 2) 10 | if (m[i - 1] == m[i]) 11 | m[curCnt++] = m[i]; 12 | if (i == size) { 13 | m[curCnt++] = m[i - 1]; 14 | part = 1; 15 | } 16 | else if (part) 17 | m[curCnt] = m[size - 2]; 18 | else if (m[size - 2] == m[size - 1]) 19 | m[curCnt] = m[size - 2]; 20 | else 21 | curCnt--; 22 | size = curCnt; 23 | } while (size > 1); 24 | *majority = m[0]; 25 | } 26 | 27 | int main(void) { 28 | CDataType majority; 29 | CDataType m[MAX] = "AAACCBBCCCBCC"; 30 | findMajority(m, 13, &majority); 31 | printf("Мажорант: %c\n", majority); 32 | return 0; 33 | } -------------------------------------------------------------------------------- /chapter07/major9.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define CDataType char 3 | 4 | void findMajority(CDataType m[], unsigned size, CDataType *majority) 5 | { unsigned i, curCnt; 6 | do { 7 | for (curCnt = 0, i = 1; i < size; i += 2) 8 | if (m[i - 1] == m[i]) 9 | m[curCnt++] = m[i]; 10 | if (size & 1) 11 | *majority = m[size - 1]; 12 | size = curCnt; 13 | } while (size > 0); 14 | } 15 | 16 | int main(void) { 17 | CDataType m[14] = "AAACCBBCCCBCC"; 18 | CDataType majority; 19 | findMajority(m, 13, &majority); 20 | printf("Мажорант: %c\n", majority); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /chapter07/maximum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | 5 | int m[MAX]; 6 | 7 | const unsigned n = 100; /* Брой елементи в масива */ 8 | 9 | void init(int m[], unsigned n) /* Запълва масива със случайни числа */ 10 | { unsigned i; 11 | for (i = 0; i < n; i++) 12 | m[i] = rand() % (2*n + 1); 13 | } 14 | 15 | void print(int m[], unsigned n) /* Извежда масива на екрана */ 16 | { unsigned i; 17 | for (i = 0; i < n; i++) 18 | printf("%8d", m[i]); 19 | } 20 | 21 | int findMax(int m[], unsigned n) /* Намира максималния елемент */ 22 | { unsigned i; 23 | int max; 24 | for (max = m[0], i = 1; i < n; i++) 25 | if (m[i] > max) 26 | max = m[i]; 27 | return max; 28 | } 29 | 30 | int findMin(int m[], unsigned n) /* Намира минималния елемент */ 31 | { unsigned i; 32 | int min; 33 | for (min = m[0], i = 1; i < n; i++) 34 | if (m[i] < min) 35 | min = m[i]; 36 | return min; 37 | } 38 | 39 | void findMinMax(int *min, int *max, const int m[], const unsigned n) 40 | /* Намира едновременно максималния и минималния елементи */ 41 | { unsigned i, n2; 42 | for (*min = *max = m[n2 = n/2], i = 0; i < n2; i++) 43 | if (m[i] > m[n-i-1]) { 44 | if (m[i] > *max) 45 | *max = m[i]; 46 | if (m[n-i-1] < *min) 47 | *min = m[n-i-1]; 48 | } 49 | else { 50 | if (m[n-i-1] > *max) 51 | *max = m[n-i-1]; 52 | if (m[i] < *min) 53 | *min = m[i]; 54 | } 55 | } 56 | 57 | void swap(int *el1, int *el2) /* Разменя стойностите на две променливи */ 58 | { int tmp = *el1; *el1 = *el2; *el2 = tmp; } 59 | 60 | int findSecondMax(int m[], unsigned n) /* Намира втория по големина елемент */ 61 | { int x,y; 62 | unsigned i; 63 | x = m[0]; y = m[1]; 64 | if (y > x) 65 | swap(&x,&y); 66 | for (i = 2; i < n; i++) 67 | if (m[i] > y) 68 | if ((y = m[i]) > x) 69 | swap(&x,&y); 70 | return y; 71 | } 72 | 73 | int main(void) { 74 | int max, min; 75 | init(m,n); 76 | printf("Масивът:\n"); print(m,n); 77 | printf("Максимален елемент: %d\n", findMax(m,n)); 78 | printf("Минимален елемент: %d\n", findMin(m,n)); 79 | findMinMax(&min, &max, m, n); 80 | printf("Минимален и максимален елемент едновременно: %d %d\n", min, max); 81 | printf("Втори по големина елемент: %d\n", findSecondMax(m,n)); 82 | return 0; 83 | } -------------------------------------------------------------------------------- /chapter07/merge_a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | 5 | int a[MAX], /* Основен масив - за сортиране */ 6 | b[MAX]; /* Помощен масив */ 7 | 8 | const unsigned n = 100; /* Брой елементи за сортиране */ 9 | 10 | /* Генерира примерно множество */ 11 | void generate(void) 12 | { unsigned i; 13 | for (i = 0; i < n; i++) 14 | a[i] = rand() % (2*n + 1); 15 | } 16 | 17 | /* Извежда списъка на екрана */ 18 | void printList(void) 19 | { unsigned i; 20 | for (i = 0; i < n; i++) 21 | printf("%4d", a[i]); 22 | } 23 | 24 | /* Сортиране */ 25 | void mergeSort(unsigned left, unsigned right) 26 | { unsigned i, j, k, mid; 27 | if (right <= left) return; /* Проверка дали има какво да се сортира */ 28 | mid = (right + left) / 2; 29 | mergeSort(left, mid); /* Сортиране на левия дял */ 30 | mergeSort(mid + 1, right); /* Сортиране на десния дял */ 31 | 32 | /* Копиране на елементите на a[] в помощния масив b[] */ 33 | for (i = mid + 1; i > left; i--) 34 | b[i - 1] = a[i - 1]; /* Права посока */ 35 | for (j = mid; j < right; j++) 36 | b[right + mid - j] = a[j + 1]; /* Обратна посока */ 37 | 38 | /* Сливане на двата масива в a[] */ 39 | for (k = left; k <= right; k++) 40 | a[k] = (b[i] < b[j]) ? b[i++] : b[j--]; 41 | } 42 | 43 | int main(void) { 44 | generate(); 45 | printf("Преди сортирането:\n"); 46 | printList(); 47 | mergeSort(0, n-1); 48 | printf("След сортирането:\n"); 49 | printList(); 50 | return 0; 51 | } -------------------------------------------------------------------------------- /chapter07/merge_l1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct list { /* Тип свързан списък */ 5 | int value; 6 | struct list *next; 7 | } *empty; /* Празен елемент */ 8 | 9 | const unsigned long n = 100; 10 | 11 | struct list *generate(unsigned long n) { /* Генерира примерно множество */ 12 | struct list *p, *q; 13 | unsigned long i; 14 | for (p = NULL, i = 0; i < n; i++) { 15 | q = (struct list *) malloc(sizeof(struct list)); 16 | q->value = rand() % (2*n + 1); 17 | q->next = p; 18 | p = q; 19 | } 20 | return p; 21 | } 22 | 23 | struct list *merge(struct list *a, struct list *b) 24 | { struct list *head, *tail; 25 | 26 | /* Предполага се, че и двата списъка съдържат поне по един елемент */ 27 | tail = head = empty; 28 | for (;;) { 29 | if (a->value < b->value) { 30 | tail->next = a; 31 | a = a->next; 32 | tail = tail->next; 33 | if (NULL == a) { 34 | tail->next = b; 35 | break; 36 | } 37 | } 38 | else { 39 | tail->next = b; 40 | b = b->next; 41 | tail = tail->next; 42 | if (NULL == b) { 43 | tail->next = a; 44 | break; 45 | } 46 | } 47 | } 48 | return head->next; 49 | } 50 | 51 | struct list *mergeSort(struct list *c, unsigned long n) 52 | { struct list *a, *b; 53 | unsigned long i, n2; 54 | 55 | /* Ако списъкът съдържа само един елемент: не се прави нищо */ 56 | if (n < 2) 57 | return c; 58 | 59 | /* Разделяне на списъка на две части */ 60 | for (a = c, n2 = n / 2, i = 2; i <= n2; i++) 61 | c = c->next; 62 | b = c->next; 63 | c->next = NULL; 64 | 65 | /* Сортиране поотделно на двете части, последвано от сливане */ 66 | return merge(mergeSort(a, n2), mergeSort(b, n - n2)); 67 | } 68 | 69 | void printList(struct list *p) { /* Извежда списъка на екрана */ 70 | for (; p != NULL; p = p->next) 71 | printf("%4d", p->value); 72 | } 73 | 74 | int main(void) { 75 | struct list *l; 76 | empty = (struct list *) malloc(sizeof(struct list)); 77 | l = generate(n); 78 | printf("Преди сортирането:\n"); printList(l); 79 | l = mergeSort(l,n); 80 | printf("След сортирането:\n"); printList(l); 81 | return 0; 82 | } -------------------------------------------------------------------------------- /chapter07/merge_l2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define INFINITY (int)((1 << (sizeof(int)*8 - 1)) - 1) 4 | 5 | 6 | struct list { /* Тип свързан списък */ 7 | int value; 8 | struct list *next; 9 | } *z; /* Празен елемент */ 10 | 11 | const unsigned long n = 100; 12 | 13 | /* Генерира примерно множество */ 14 | struct list *generate(unsigned long n) 15 | { struct list *p, *q; 16 | unsigned long i; 17 | for (p = z, i = 0; i < n; i++) { 18 | q = (struct list *) malloc(sizeof(struct list)); 19 | q->value = rand() % (2*n + 1); 20 | q->next = p; 21 | p = q; 22 | } 23 | return p; 24 | } 25 | 26 | void printList(struct list *p) /* Извежда списъка на екрана */ 27 | { for (; p != z; p = p->next) 28 | printf("%4d", p->value); 29 | } 30 | 31 | struct list *merge(struct list *a, struct list *b) 32 | { struct list *c; 33 | c = z; 34 | 35 | /* Предполага се, че и двата списъка съдържат поне по един елемент */ 36 | do { 37 | if (a->value < b->value) { 38 | c->next = a; 39 | c = a; 40 | a = a->next; 41 | } 42 | else { 43 | c->next = b; 44 | c = b; 45 | b = b->next; 46 | } 47 | } while (c != z); 48 | c = z->next; 49 | z->next = z; 50 | return c; 51 | } 52 | 53 | struct list *mergeSort(struct list *c) 54 | { struct list *a, *b; 55 | 56 | /* Ако списъкът съдържа само един елемент: не се прави нищо */ 57 | if (c->next == z) 58 | return c; 59 | 60 | /* Списъкът се разделя на две части */ 61 | for (a = c, b = c->next->next->next; b != z; c = c->next) 62 | b = b->next->next; 63 | b = c->next; 64 | c->next = z; 65 | 66 | /* Сортиране поотделно на двете части, последвано от сливане */ 67 | return merge(mergeSort(a), mergeSort(b)); 68 | } 69 | 70 | int main(void) { 71 | struct list *l; 72 | 73 | /* Инициализация на z */ 74 | z = (struct list *) malloc(sizeof(struct list)); 75 | z->value = INFINITY; 76 | z->next = z; 77 | 78 | l = generate(n); 79 | printf("Преди сортирането:\n"); 80 | printList(l); 81 | l = mergeSort(l); /* Предполага се, че списъкът съдържа поне 1 елемент */ 82 | printf("След сортирането:\n"); 83 | printList(l); 84 | return 0; 85 | } -------------------------------------------------------------------------------- /chapter07/mergearr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX 12 7 | #define ARRAYS 6 8 | 9 | struct CElem { 10 | int key; 11 | /* ............. 12 | Някакви данни 13 | ............. */ 14 | }; 15 | 16 | struct CList { 17 | unsigned len, point; 18 | struct CElem data[MAX]; 19 | struct CList *next; 20 | }; 21 | 22 | struct CList *init(unsigned mod) /* Запълва масива със случайни цели числа */ 23 | { struct CList *head, *p; 24 | unsigned i, j; 25 | srand(time(NULL)); 26 | for (head = NULL, i = 0; i < ARRAYS; i++) { 27 | p = (struct CList *) malloc(sizeof(struct CList)); 28 | p->len = MAX; 29 | p->point = 0; 30 | p->data[0].key = (rand() % mod); 31 | for (j = 1; jdata[j].key = p->data[j-1].key + (rand() % mod); 34 | p->next = head; 35 | head = p; 36 | } 37 | 38 | return head; 39 | } 40 | 41 | void merge(struct CList *head) { 42 | struct CList *p, *q, *pMin; 43 | struct CElem k1, k2; 44 | int i; 45 | printf("\n"); 46 | p = (struct CList *) malloc(sizeof(struct CList)); 47 | p->next = head; 48 | head = p; 49 | for (i = 0; i < MAX*ARRAYS; i++) { 50 | p = head; pMin = head; 51 | while (NULL != p->next) { 52 | k1 = p->next->data[p->next->point]; 53 | k2 = pMin->next->data[pMin->next->point]; 54 | if (k1.key < k2.key) 55 | pMin = p; 56 | p = p->next; 57 | } 58 | printf("%8d", pMin->next->data[pMin->next->point].key); 59 | if (pMin->next->len-1 == pMin->next->point) { 60 | q = pMin->next; 61 | pMin->next = pMin->next->next; 62 | free(q); 63 | } 64 | else 65 | pMin->next->point++; 66 | } 67 | } 68 | 69 | void print(struct CList *head) 70 | { unsigned i; 71 | for (; NULL != head; head = head->next) { 72 | for (i = 0; i < MAX; i++) 73 | printf("%6d", head->data[i].key); 74 | printf("\n"); 75 | } 76 | printf("\n"); 77 | } 78 | 79 | int main(void) 80 | { struct CList *head; 81 | head = init(500); 82 | printf("\nМасивите преди сортирането:\n"); 83 | print(head); 84 | printf("Резултатът от сливането:"); 85 | merge(head); 86 | return 0; 87 | } -------------------------------------------------------------------------------- /chapter07/mid_el2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | 5 | int m[MAX]; 6 | 7 | const unsigned n = 100; /* Брой елементи в масива */ 8 | const unsigned k = 10; /* Пореден номер на търсения елемент */ 9 | 10 | void init(int m[], unsigned n) /* Запълва масива със случайни числа */ 11 | { unsigned i; 12 | for (i = 0; i < n; i++) 13 | m[i] = rand() % (2*n+1); 14 | } 15 | 16 | void swap(int *el1, int *el2) /* Разменя стойностите на две променливи */ 17 | { int tmp = *el1; *el1 = *el2; *el2 = tmp; } 18 | 19 | unsigned partition(unsigned l, unsigned r) /* Разделяне по Ломуто */ 20 | { int i; 21 | unsigned j; 22 | int x; 23 | i = l - 1; x = m[r]; 24 | for (j = l; j <= r; j++) 25 | if (m[j] <= x) { 26 | i++; 27 | swap(m+i,m+j); 28 | } 29 | if (i == (int)r) /* Всички елементи са <= x. Стесняване на областта с 1. */ 30 | i--; 31 | return i; 32 | } 33 | 34 | unsigned find(int l, int r, unsigned k) /* Търсене на k-ия елемент по Хоор */ 35 | { unsigned mid, p; 36 | if (l == r) 37 | return l; 38 | mid = partition(l,r); 39 | p = mid - l + 1; 40 | return k < p ? find(l,mid,k) : find(mid+1,r,k-p); 41 | } 42 | 43 | void print(int m[], unsigned n) /* Извежда масива на екрана */ 44 | { unsigned i; 45 | for (i = 0; i < n; i++) 46 | printf("%8d", m[i]); 47 | } 48 | 49 | int main(void) { 50 | init(m,n); 51 | printf("Масивът преди търсенето:"); print(m,n); 52 | printf("\nТърсим k-ия елемент: k=%u", k); 53 | printf("\nМасивът след търсенето:"); print(m,n); 54 | printf("\nk-ият елемент е: %d", m[find(0,n-1,k)]); 55 | return 0; 56 | } -------------------------------------------------------------------------------- /chapter07/mid_elem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | int m[MAX]; 5 | 6 | const unsigned n = 100; /* Брой елементи в масива */ 7 | const unsigned k = 10; /* Пореден номер на търсения елемент */ 8 | 9 | void init(int m[], unsigned n) /* Запълва масива със случайни числа */ 10 | { unsigned i; 11 | for (i = 0; i < n; i++) 12 | m[i] = rand() % (2*n+1); 13 | } 14 | 15 | void swap(int *el1, int *el2) /* Разменя стойностите на две променливи */ 16 | { int tmp = *el1; *el1 = *el2; *el2 = tmp; } 17 | 18 | void find(int m[], unsigned n, unsigned k) /* намира k-ия елемент */ 19 | { int i,j,l,r; 20 | int x; 21 | l = 0; r = n - 1; 22 | while (l < r) { 23 | x = m[k]; i = l; j = r; 24 | for(;;) { 25 | while (x > m[i]) i++; 26 | while (x < m[j]) j--; 27 | if (i > j) 28 | break; 29 | swap(m + i, m + j); 30 | i++; 31 | j--; 32 | } 33 | if (j < (int)k) 34 | l = i; 35 | if ((int)k < i) 36 | r = j; 37 | } 38 | } 39 | 40 | void print(int m[], unsigned n) /* Извежда масива на екрана */ 41 | { unsigned i; 42 | for (i = 0; i < n; i++) 43 | printf("%8d", m[i]); 44 | } 45 | 46 | int main(void) { 47 | init(m,n); 48 | printf("Масивът преди търсенето:"); print(m,n); 49 | printf("\nТърсим k-ия елемент: k=%u", k); 50 | find(m,n,k); 51 | printf("\nМасивът след търсенето:"); print(m,n); 52 | printf("\nk-ият елемент е: %d", m[k]); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /chapter07/powrec.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const double base = 3.14; 4 | const unsigned d = 11; 5 | 6 | double power(double x, unsigned n) 7 | { if (0 == n) return 1; 8 | else 9 | if (n % 2) return x * power(x, n - 1); 10 | else return power(x * x, n / 2); 11 | } 12 | int main(void) { 13 | printf("%lf^%u = %lf\n", base, d, power(base, d)); 14 | return 0; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /chapter07/shift1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | 6 | struct CElem { 7 | int data; 8 | /* ... */ 9 | } m[MAX]; 10 | 11 | const unsigned n = 10; /* Брой елементи в масива */ 12 | const unsigned k = 2; /* Брой позиции на отместване */ 13 | 14 | void init(void) 15 | { unsigned i; 16 | for (i = 0; i < n; i++) 17 | m[i].data = i; 18 | } 19 | 20 | unsigned gcd(unsigned x, unsigned y) 21 | { while (y > 0) { 22 | unsigned tmp = y; 23 | y = x % y; 24 | x = tmp; 25 | } 26 | return x; 27 | } 28 | 29 | void shiftLeft1(unsigned k) 30 | { /* Измества масива m на k позиции наляво, като използва помощна променлива */ 31 | unsigned i, ths, next, gcdNK; 32 | struct CElem tmp; 33 | 34 | for (gcdNK = gcd(n, k), i = 0; i < gcdNK; i++) { 35 | ths = i; tmp = m[ths]; 36 | next = ths + k; 37 | if (next >= n) 38 | next -= n; 39 | while (next != i) { 40 | m[ths] = m[next]; 41 | ths = next; 42 | next += k; 43 | if (next >= n) 44 | next -= n; 45 | } 46 | m[ths] = tmp; 47 | } 48 | } 49 | 50 | void print(void) 51 | { unsigned i; 52 | for (i = 0; i < n; i++) 53 | printf("%d ", m[i].data); 54 | printf("\n"); 55 | } 56 | 57 | int main(void) { 58 | init(); 59 | shiftLeft1(k); 60 | print(); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /chapter07/shift2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | 6 | struct CElem { 7 | int data; 8 | /* ... */ 9 | } m[MAX]; 10 | 11 | const unsigned n = 10; /* Брой елементи в масива */ 12 | const unsigned k = 2; /* Брой позицции на отместване */ 13 | 14 | void init(void) 15 | { unsigned i; 16 | for (i = 0; i < n; i++) 17 | m[i].data = i; 18 | } 19 | 20 | void swap(unsigned a, unsigned b, unsigned l) 21 | { /* Разменя местата на подмасивите m[a..a+l-1] и m[b..b+l-1] */ 22 | unsigned i; 23 | struct CElem tmp; 24 | for (i = 0; i < l; i++) { 25 | tmp = m[a + i]; 26 | m[a + i] = m[b + i]; 27 | m[b + i] = tmp; 28 | } 29 | } 30 | 31 | void shiftLeft2(unsigned k) 32 | { /* Измества масива m[] на k позиции наляво. 33 | * рекурсивен процес, реализиран итеративно } */ 34 | unsigned i, j, p; 35 | p = i = k; 36 | j = n - k; 37 | while (i != j) 38 | if (i > j) { 39 | swap(p - i, p, j); 40 | i -= j; 41 | } 42 | else { 43 | swap(p - i, p + j - i, i); 44 | j -= i; 45 | } 46 | swap(p - i, p, i); 47 | } 48 | 49 | void print(void) 50 | { unsigned i; 51 | for (i = 0; i < n; i++) 52 | printf("%d ", m[i].data); 53 | printf("\n"); 54 | } 55 | 56 | int main(void) { 57 | init(); 58 | shiftLeft2(k); 59 | print(); 60 | return 0; 61 | } -------------------------------------------------------------------------------- /chapter07/shift3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 100 5 | 6 | struct CElem { 7 | int data; 8 | /* ... */ 9 | } m[MAX]; 10 | 11 | const unsigned n = 10; /* Брой елементи в масива */ 12 | const unsigned k = 2; /* Брой позицции на отместване */ 13 | 14 | void init(void) 15 | { unsigned i; 16 | for (i = 0; i < n; i++) 17 | m[i].data = i; 18 | } 19 | 20 | void reverse(unsigned a, unsigned b) /* Обръща подмасива m[a..b] */ 21 | { unsigned i, j, k, cnt; 22 | struct CElem tmp; 23 | for (cnt = (b - a) / 2, k = a, j = b, i = 0; i <= cnt; i++, j--, k++) { 24 | tmp = m[k]; 25 | m[k] = m[j]; 26 | m[j] = tmp; 27 | } 28 | } 29 | 30 | void shiftLeft3(unsigned k) 31 | { /* Измества масива m на k позиции наляво, на три стъпки */ 32 | reverse(0, k - 1); 33 | reverse(k, n - 1); 34 | reverse(0, n - 1); 35 | } 36 | 37 | void print(void) 38 | { unsigned i; 39 | for (i = 0; i < n; i++) 40 | printf("%d ", m[i].data); 41 | printf("\n"); 42 | } 43 | 44 | int main(void) { 45 | init(); 46 | shiftLeft3(k); 47 | print(); 48 | return 0; 49 | } -------------------------------------------------------------------------------- /chapter07/tourn1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | unsigned m[MAX][MAX]; 5 | 6 | void copyMatrix(unsigned stX, unsigned stY, unsigned cnt, unsigned add) 7 | { unsigned i, j; 8 | for (i = 0; i < cnt; i++) 9 | for (j = 0; j < cnt; j++) 10 | m[i + stX][j + stY] = m[i + 1][j + 1] + add; 11 | } 12 | 13 | void findSolution(unsigned n) /* Построява таблицата */ 14 | { unsigned i; 15 | m[1][1] = 0; 16 | for (i = 1; i <= n; i <<= 1) { 17 | copyMatrix(i + 1, 1, i, i); 18 | copyMatrix(i + 1, i + 1, i, 0); 19 | copyMatrix(1, i + 1, i, i); 20 | } 21 | } 22 | 23 | void print(unsigned n) /* Извежда резултата */ 24 | { unsigned i, j; 25 | for (i = 1; i <= n; i++) { 26 | for (j = 1; j <= n; j++) 27 | printf("%3u", m[i][j]); 28 | printf("\n"); 29 | } 30 | } 31 | 32 | int main(void) { 33 | const unsigned n = 8; 34 | findSolution(n); 35 | print(n); 36 | return 0; 37 | } -------------------------------------------------------------------------------- /chapter07/tourn2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | unsigned m[MAX][MAX]; 5 | 6 | void copyMatrix(unsigned stX, unsigned stY, unsigned cnt, unsigned add) 7 | { unsigned i, j; 8 | for (i = 0; i < cnt; i++) 9 | for (j = 0; j < cnt; j++) 10 | m[i + stX][j + stY] = m[i + 1][j + 1] + add; 11 | } 12 | 13 | void findSolution(unsigned n) /* Построява таблицата */ 14 | { unsigned i; 15 | if (n % 2 == 0) /* Ако n е четно, задачата се свеждаме към n-1 */ 16 | n--; 17 | 18 | /* Попълва се таблицата за n - тук е гарантирано нечетно. */ 19 | for (i = 0; i < n * (n + 1); i++) 20 | m[i % (n + 1)][i / (n + 1)] = i % n + 1; 21 | 22 | /* Възстановява се стойността на n */ 23 | if (n % 2 == 1) n++; 24 | 25 | for (i = 0; i < n; i++) { 26 | if (n % 2 == 0) /* Запълват се последният стълб и ред при четно n */ 27 | m[i][n - 1] = m[n - 1][i] = m[i][i]; 28 | m[i][i] = 0; /* Запълва се с 0 главният диагонал */ 29 | } 30 | } 31 | 32 | void print(unsigned n) /* Извежда резултата */ 33 | { unsigned i, j; 34 | for (i = 0; i < n; i++) { 35 | for (j = 0; j < n; j++) 36 | printf("%3u", m[i][j]); 37 | printf("\n"); 38 | } 39 | } 40 | 41 | int main(void) { 42 | const unsigned n = 5; 43 | findSolution(n); 44 | print(n); 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter07/tourn3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | unsigned m[MAX][MAX]; 5 | 6 | void copyMatrix(unsigned stX, unsigned stY, unsigned cnt, unsigned add) 7 | { unsigned i, j; 8 | for (i = 0; i < cnt; i++) 9 | for (j = 0; j < cnt; j++) 10 | m[i + stX][j + stY] = m[i + 1][j + 1] + add; 11 | } 12 | 13 | void findSolution(unsigned n) /* Построява таблицата */ 14 | { unsigned i, j; 15 | if (n % 2 == 0) /* Ако n е четно, задачата се свежда към n-1 */ 16 | n--; 17 | 18 | /* Попълване на таблицата за n - тук е гарантирано нечетно. */ 19 | for (i = 0; i < n; i++) 20 | for (j = 0; j < n; j++) 21 | m[i][j] = i + j < n ? i + j + 1 : i + j + 1 - n; 22 | 23 | /* Възстановяване на стойността на n */ 24 | if (n % 2 == 1) n++; 25 | 26 | for (i = 0; i < n; i++) { 27 | if (n % 2 == 0) /* Запълване на последния стълб и ред при четно n */ 28 | m[i][n - 1] = m[n - 1][i] = m[i][i]; 29 | m[i][i] = 0; /* Запълване с 0 на главния диагонал */ 30 | } 31 | } 32 | 33 | void print(unsigned n) /* Извежда резултата */ 34 | { unsigned i, j; 35 | for (i = 0; i < n; i++) { 36 | for (j = 0; j < n; j++) 37 | printf("%3u", m[i][j]); 38 | printf("\n"); 39 | } 40 | } 41 | 42 | int main(void) { 43 | const unsigned n = 5; 44 | findSolution(n); 45 | print(n); 46 | return 0; 47 | } -------------------------------------------------------------------------------- /chapter08/alanbob.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 /* Максимален брой предмети */ 3 | #define MAXVALUE 200 /* Максимална стойност на отделен предмет */ 4 | 5 | unsigned char can[MAX * MAXVALUE]; /* Може ли да се получи съответната сума? */ 6 | 7 | const unsigned m[MAX] = {3,2,3,2,2,77,89,23,90,11}; /* Стойност на всеки от предметите */ 8 | const unsigned n = 10; /* Общ брой на предметите за поделяне */ 9 | 10 | void solve(void) 11 | { unsigned long p; /* Обща стойност на предметите за поделяне */ 12 | unsigned i, j; 13 | 14 | /* Пресмятане на сумата p */ 15 | for (p = i = 0; i < n; p += m[i++]) 16 | ; 17 | 18 | /* Начално инициализиране */ 19 | for (i = 1; i <= p; i++) 20 | can[i] = 0; 21 | can[0] = 1; 22 | 23 | /* Намиране на всевъзможните суми от стойности на подаръците */ 24 | for (i = 0; i < n; i++) 25 | for (j = p; j+1 > 0; j--) 26 | if (can[j]) 27 | can[j + m[i]] = 1; 28 | 29 | /* Намиране на най-близката до p/2 стойност */ 30 | for (i = p / 2; i > 1; i--) 31 | if (can[i]) { 32 | printf("\n%s%u%s%lu", "сума за Алан: ", i, "; сума за Боб: ", p - i); 33 | return; 34 | } 35 | } 36 | 37 | int main(void) 38 | { solve(); 39 | return 0; 40 | } -------------------------------------------------------------------------------- /chapter08/alanbob2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 /* Максимален брой предмети */ 3 | #define MAXVALUE 200 /* Максимална стойност на отделен предмет */ 4 | #define NOT_SET (unsigned)(-1) 5 | 6 | unsigned last[MAX * MAXVALUE]; /* Кой предмет е бил добавен последен? */ 7 | 8 | const unsigned m[MAX] = {3,2,3,2,2,77,89,23,90,11}; /* Стойност на всеки от предметите */ 9 | const unsigned n = 10; /* Общ брой на предметите за поделяне */ 10 | 11 | void solve(void) 12 | { unsigned long p; /* Обща стойност на предметите за поделяне */ 13 | unsigned long curSum = 0; 14 | unsigned i, j; 15 | 16 | /* Пресмятане на сумата p */ 17 | for (p = i = 0; i < n; p += m[i++]) 18 | ; 19 | 20 | /* Начално инициализиране */ 21 | for (last[0] = 0, i = 1; i <= p; i++) 22 | last[i] = NOT_SET; 23 | 24 | /* Намиране на всевъзможните суми от стойности на подаръците */ 25 | for (i = 0; i < n; i++) { 26 | for (j = p; j+1 > 0; j--) 27 | if (NOT_SET != last[j] && NOT_SET == last[j + m[i]]) 28 | last[j + m[i]] = i; 29 | curSum += m[i]; 30 | } 31 | 32 | /* Намиране на най-близката до p/2 стойност и извеждане на решението */ 33 | for (i = p / 2; i > 1; i--) { 34 | if (NOT_SET != last[i]) { 35 | printf("\n%s%u%s%lu", "Сума за Алан: ", i, "; сума за Боб: ", p - i); 36 | printf("\nАлан взема:"); 37 | while (i > 0) { 38 | printf(" %u", m[last[i]]); 39 | i -= m[last[i]]; 40 | } 41 | printf("\nБоб взема останалите подаръци."); 42 | return; 43 | } 44 | } 45 | } 46 | 47 | int main(void) 48 | { solve(); 49 | return 0; 50 | } -------------------------------------------------------------------------------- /chapter08/binom.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Неефективен рекурсивен вариант */ 4 | unsigned long binom(unsigned n, unsigned k) 5 | { if (k > n) return 0; 6 | else if (0 == k || k == n) return 1; 7 | else return binom(n-1, k-1) + binom(n-1, k); 8 | } 9 | 10 | int main(void) { 11 | printf("%lu\n", binom(7,3)); 12 | return 0; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /chapter08/binom2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX 200 4 | 5 | /* Динамично оптимиране */ 6 | unsigned long m[MAX]; 7 | unsigned long binomDynamic(unsigned n, unsigned k) 8 | { unsigned i, j; 9 | for (i = 0; i <= n; i++) { 10 | m[i] = 1; 11 | if (i > 1) { 12 | if (k < i - 1) j = k; else j = i - 1; 13 | for (; j >= 1; j--) m[j] += m[j - 1]; 14 | } 15 | } 16 | return m[k]; 17 | } 18 | 19 | int main(void) { 20 | printf("%lu\n", binomDynamic(7,3)); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /chapter08/board.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 1000 3 | 4 | unsigned F[MAX]; /* Целева функция */ 5 | unsigned next[MAX]; /* Следващ проводник */ 6 | 7 | const unsigned n = 9; /* Брой накрайници */ 8 | const unsigned p[MAX] = {0,9,1,3,6,2,7,5,4,8}; /* Изходна пермутация */ 9 | 10 | void solve(void) 11 | { unsigned k, i; 12 | /* Инициализация */ 13 | for (i = 1; i <= n; i++) { 14 | F[i] = 1; 15 | next[i] = 0; 16 | } 17 | /* Основен цикъл */ 18 | for (k = n; k >= 1; k--) 19 | for (i = k + 1; i <= n; i++) 20 | if (p[k] < p[i]) 21 | if (1 + F[i] > F[k]) { 22 | F[k] = 1 + F[i]; 23 | next[k] = i; 24 | } 25 | } 26 | 27 | /* Извежда резултата на екрана */ 28 | void print(void) 29 | { unsigned i, max, index; 30 | for (max = F[index = 1], i = 2; i <= n; i++) 31 | if (F[i] > max) { 32 | max = F[i]; 33 | index = i; 34 | } 35 | printf("\nМаксимален брой кабели: %u\n", max); 36 | do { 37 | printf("%u ", index); 38 | index = next[index]; 39 | } while (index); 40 | } 41 | 42 | int main(void) { 43 | solve(); 44 | print(); 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter08/breaknum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | unsigned long M[MAX][MAX]; /* Целева функция */ 5 | 6 | const unsigned n = 10; 7 | 8 | /* Намира броя на представянията на n като сума от естествени числа */ 9 | unsigned long getNum(unsigned n) 10 | { unsigned i, j; 11 | for (i = 1; i <= n; i++) 12 | for (j = 1; j <= n; j++) 13 | if (1 == j) 14 | M[i][j] = 1; 15 | else if (1 == i) 16 | M[i][j] = 1; 17 | else if (i < j) 18 | M[i][j] = M[i][i]; 19 | else if (i == j) 20 | M[i][j] = 1 + M[i][i - 1]; 21 | else 22 | M[i][j] = M[i][j - 1] + M[i - j][j]; 23 | return M[n][n]; 24 | } 25 | 26 | int main(void) 27 | { 28 | printf("Броят на представянията на %u като сума от естествени числа е: %lu", 29 | n, getNum(n)); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /chapter08/catalan.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 80 4 | #define INFINITY 1e20 5 | 6 | double d[MAX][MAX]; /* Разстояния между върховете */ 7 | double m[MAX][MAX]; /* Таблица - целева функция */ 8 | 9 | const struct { /* Координати на върховете */ 10 | int x; 11 | int y; 12 | } coord[MAX] = {{1,1},{5,-2},{10,1},{7,7},{1,7}}; 13 | const unsigned n = 5; /* Брой върхове */ 14 | 15 | /* Пресмята разстоянията между всички двойки върхове */ 16 | void calcDist(void) 17 | { unsigned i, j; 18 | for (i = 0; i < n - 1; i++) 19 | for (j = i + 1; j < n; j++) 20 | d[i][j] = sqrt((coord[i].x - coord[j].x) * (coord[i].x - coord[j].x) + 21 | (coord[i].y - coord[j].y) * (coord[i].y - coord[j].y)); 22 | } 23 | 24 | /* Формира таблица, съдържаща минималния брой умножения, необходими за 25 | * умножението на всяка двойка матрици, както и индексът, за който се постига */ 26 | void solve(void) 27 | { unsigned i, j, k; 28 | for (i = 1; i < n; i++) 29 | m[i][i] = 0; /* Инициализация */ 30 | for (j = 1; j < n; j++) { /* Основен цикъл */ 31 | for (i = 1; i < n - j; i++) { 32 | m[i][i + j] = INFINITY; 33 | for (k = i; k < i + j; k++) { 34 | double t = m[i][k] + 35 | m[k+1][i+j] + 36 | d[i-1][k] + 37 | d[k][i+j] + 38 | d[i-1][i+j]; 39 | if (t < m[i][i+j]) { /* Подобряване на текущото решение */ 40 | m[i][i+j] = t; 41 | m[i+j][i] = k; 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | /* Отпечатване на резултата */ 49 | void printResult(void) 50 | { unsigned i; 51 | double p = d[0][n-1]; /* Пресмятаме периметъра */ 52 | for (i = 0; i < n; i++) 53 | p += d[i][i+1]; 54 | printf("\nДължината на минималния разрез е %.2lf", (m[1][n-1] - p) / 2); 55 | } 56 | 57 | /* Извеждане на минималния разрез на екрана */ 58 | void writeCut(unsigned ll, unsigned rr) 59 | { if (ll != rr) { 60 | writeCut(ll, (unsigned) m[rr][ll]); 61 | writeCut((unsigned) m[rr][ll] + 1, rr); 62 | if (ll != 1 || rr != n-1) 63 | printf("(%u,%u) ", ll, rr + 1); 64 | } 65 | } 66 | 67 | int main(void) { 68 | calcDist(); 69 | solve(); 70 | printResult(); 71 | printf("\nДиагонали от минималния разрез: "); 72 | writeCut(1, n-1); 73 | return 0; 74 | } -------------------------------------------------------------------------------- /chapter08/cfl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 30 /* Максимален брой правила за извод */ 4 | #define LETTERS 26 /* Брой букви */ 5 | 6 | const struct { /* Продукции, отиващи в терминали: S->a */ 7 | char S, a; 8 | } prodT[MAX+1] = { 9 | {0,0}, /* не се използва */ 10 | {'S','s'}, /* S->s */ 11 | {'A','a'}, /* A->a */ 12 | {'B','b'} /* B->b */ 13 | }; 14 | const unsigned cntT = 3; /* Брой правила от вида 1: S->a */ 15 | const char string[MAX + 1] = "aaasbbb"; /* Низ, който проверяваме за принадлежност към граматиката */ 16 | 17 | const struct { /* Продукции, отиващи в нетерминали: S->AB */ 18 | char S, A, B; 19 | } prodNT[MAX+1] = { 20 | {0,0,0}, /* не се използва */ 21 | {'S','A','R'}, /* S->AR */ 22 | {'S','A','B'}, /* S->AB */ 23 | {'R','S','B'}, /* R->SB */ 24 | }; 25 | const unsigned cntNT = 3; /* Брой правила от вида 2: S->AB */ 26 | 27 | unsigned char t[LETTERS][MAX][MAX]; /* Целева функция */ 28 | 29 | /* Проверява */ 30 | unsigned cfl(void) 31 | { unsigned i, j, k, l, d, let, n; 32 | /* Инициализация */ 33 | n = strlen(string); /* Дължина на проверявания низ */ 34 | /* Запълваме масива с "неистина" */ 35 | for (i = 1; i <= n; i++) 36 | for (j = 1; j <= n; j++) 37 | for (let = 0; let < LETTERS; let++) 38 | t[let][i][j] = 0; 39 | /* Установяваме в истина всички директни продукции, които ни вършат работа */ 40 | for (i = 1; i <= cntT; i++) 41 | for (j = 1; j <= n; j++) 42 | if (prodT[i].a == string[j - 1]) 43 | t[prodT[i].S - 'A'][j][j] = 1; 44 | /* Основен цикъл по правилата от тип 2 */ 45 | for (d = 1; d < n; d++) 46 | for (i = 1; i <= n - d; i++) 47 | for (j = i + d, k = 1; k <= cntNT; k++) /* За всеки нетерминал S от лява част на правило */ 48 | for (l = i; l <= j - 1; l++) 49 | if (t[prodNT[k].A - 'A'][i][l] && t[prodNT[k].B - 'A'][l + 1][j]) 50 | t[prodNT[k].S - 'A'][i][j] = 1; 51 | return t['S' - 'A'][1][n]; 52 | } 53 | 54 | int main(void) { 55 | printf("\nНизът %s%s", cfl() ? "" : "НЕ ", "се извежда от граматиката!"); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /chapter08/coin_min.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXCOINS 100 /* Максимален брой монети */ 3 | #define MAXSUM 100 /* Максимална сума */ 4 | 5 | unsigned long F[MAXSUM][MAXSUM]; /* Целева функция */ 6 | unsigned char exist[MAXSUM]; /* Съществува ли монета с такава стойност */ 7 | 8 | const unsigned coins[MAXCOINS] = {1,2,3,4,6}; /* Налични типове монети */ 9 | const unsigned sum = 6; /* Сума, която искаме да получим */ 10 | const unsigned n = 5; /* Общ брой налични монети */ 11 | 12 | /* Инициализираща функция */ 13 | void init(void) 14 | { unsigned i, j; 15 | /* Нулиране на целевата функция */ 16 | for (i = 0; i <= sum; i++) 17 | for (j = 0; j <= sum; j++) 18 | F[i][j] = 0; 19 | /* Друго представяне на стойностите на монетите за по-бърз достъп */ 20 | for (i = 0; i <= sum; i++) 21 | exist[i] = 0; 22 | for (i = 0; i < n; i++) 23 | exist[coins[i]] = 1; 24 | } 25 | 26 | /* Намира броя на представянията на sum */ 27 | unsigned long count(unsigned sum, unsigned max) 28 | { unsigned long i; 29 | if (sum <= 0) 30 | return 0; 31 | if (F[sum][max] > 0) 32 | return F[sum][max]; 33 | else { 34 | if (sum < max) 35 | max = sum; 36 | if (sum == max && exist[sum]) /* Съществува монета с такава стойност */ 37 | F[sum][max] = 1; 38 | for (i = max; i > 0; i--) /* Пресмятаме всички */ 39 | if (exist[i]) 40 | F[sum][max] += count(sum - i, i); 41 | } 42 | return F[sum][max]; 43 | } 44 | 45 | int main(void) { 46 | init(); 47 | printf("\nБроят на представянията на %u с наличните монети е %lu", 48 | sum, count(sum, sum)); 49 | return 0; 50 | } -------------------------------------------------------------------------------- /chapter08/coinmin2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXCOINS 100 /* Максимален брой монети */ 3 | #define MAXSUM 100 /* Максимална сума */ 4 | #define SWAP(a, b) { a = a ^ b; b = a ^ b; a = a ^ b; } 5 | 6 | unsigned long F[MAXSUM][MAXSUM]; /* Целева функция */ 7 | 8 | const unsigned n = 7; /* Общ брой налични монети */ 9 | const unsigned sum = 6; /* Сума, която искаме да получим */ 10 | unsigned coins[MAXCOINS] = {1,2,2,3,3,4,6}; /* Налични типове монети */ 11 | 12 | /* Инициализираща функция */ 13 | void init(void) 14 | { unsigned i, j; 15 | /* Нулиране на целевата функция */ 16 | for (i = 0; i <= sum; i++) 17 | for (j = 0; j <= sum; j++) 18 | F[i][j] = 0; 19 | } 20 | 21 | /* Сортира монетите в нарастващ ред */ 22 | void sort(void) 23 | { unsigned i, j; 24 | for (i = 0; i < n - 1; i++) 25 | for (j = i + 1; j < n; j++) 26 | if (coins[i] > coins[j]) 27 | SWAP(coins[i], coins[j]); 28 | } 29 | 30 | /* Намира броя на представянията на sum при използване на първите k монети */ 31 | unsigned long count(int sum, int k) 32 | { unsigned j; 33 | if (sum <= 0 || k < 0) 34 | return 0; 35 | if (F[sum][k] > 0) 36 | return F[sum][k]; 37 | else { 38 | if (coins[k] == (unsigned)sum) 39 | F[sum][k] = 1; 40 | F[sum][k] += count(sum - coins[k], k - 1); 41 | j = k; 42 | while (coins[j] == coins[k]) j--; 43 | F[sum][k] += count(sum, j); 44 | } 45 | return F[sum][k]; 46 | } 47 | 48 | int main(void) { 49 | init(); 50 | sort(); 51 | printf("\nБроят на представянията на %u с наличните монети е %lu.", 52 | sum, count(sum, n - 1)); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /chapter08/coins.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXCOINS 100 /* Максимален брой монети */ 3 | #define MAXSUMA 1000 /* Максимална сума */ 4 | 5 | struct { 6 | unsigned num; /* Брой монети в сумата */ 7 | unsigned last; /* Последна добавена монета */ 8 | } sums[MAXSUMA]; /* Целева функция */ 9 | 10 | /* Стойности на монетите */ 11 | const unsigned coins[MAXCOINS] = {0,5,2,2,3,2,2,2,4,3,5,8,6,7,9}; 12 | const unsigned sum = 31; /* Сума, чието представяне минимизираме */ 13 | const unsigned n = 14; /* Общ брой налични монети */ 14 | 15 | /* Дали можем да използваме j-тата монета в i-тата сума? */ 16 | char canJ(unsigned i, unsigned j) 17 | { int k = i - coins[j]; 18 | if (k > 0 && sums[k].num < MAXCOINS) 19 | while (k > 0) { 20 | if (sums[k].last == j) break; /* j-тата монета участва в сумата */ 21 | k -= coins[sums[k].last]; 22 | } 23 | return(0 == k); 24 | } 25 | 26 | /* Намира представяне на сумата Sum с минимален брой монети */ 27 | void findMin(unsigned sum) 28 | { unsigned i, j; 29 | sums[0].num = 0; 30 | for (i = 1; i <= sum; i++) { 31 | sums[i].num = MAXCOINS; 32 | for (j = 1; j <= n; j++) { 33 | if (canJ(i, j)) 34 | if ((sums[i - coins[j]].num + 1) < sums[i].num) { 35 | sums[i].num = 1 + sums[i - coins[j]].num; 36 | sums[i].last = j; 37 | } 38 | } 39 | } 40 | } 41 | 42 | void print(unsigned sum) 43 | { /* Извежда намереното представяне */ 44 | if (sums[sum].num == MAXCOINS) 45 | printf("\nСумата не може да се получи с наличните монети."); 46 | else { 47 | printf("\nМинимален брой необходими монети: %u", sums[sum].num); 48 | printf("\nЕто и стойностите на самите монети: "); 49 | while (sum > 0) { 50 | printf("%u ", coins[sums[sum].last]); 51 | sum -= coins[sums[sum].last]; 52 | } 53 | } 54 | } 55 | 56 | int main(void) { 57 | printf("\n%s %u %s", "Как да получим сума от", 58 | sum,"лева с минимален брой монети?"); 59 | findMin(sum); 60 | print(sum); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /chapter08/domino.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | #define BASE 10 /* Основа на бройната система */ 4 | unsigned succ[MAX]; /* Наследници за всеки връх */ 5 | unsigned F[BASE]; /* F[i]: текуща макс. дължина на подредица с най-старша цифра i */ 6 | unsigned ind[BASE]; /* ind[i]: индекс на първия член на редицата с първа цифра i */ 7 | 8 | const unsigned n = 17; /* Брой елементи в редицата */ 9 | const unsigned x[MAX] = {0, 72, 121, 1445, 178, 123, 3462, 762, 33434, 444, 10 | 472, 4, 272, 4657, 7243, 7326, 3432, 3465}; /* Редица */ 11 | 12 | /* Намира максимална домино-редица */ 13 | void solve(void) 14 | { unsigned i, l, r; 15 | 16 | for (i = 0; i < BASE; i++) 17 | F[i] = ind[i] = 0; 18 | 19 | /* Намиране дължините на редиците, започващи с всяка от цифрите от 0 до 9 */ 20 | for (i = n; i > 0; i--) { 21 | /* Определяне на най-старшата и най-младшата цифри на числото */ 22 | r = x[i] % BASE; 23 | l = x[i]; 24 | while (l > BASE) 25 | l /= BASE; 26 | /* Евентуално актуализиране на редицата, започваща със старшата цифра */ 27 | if (F[r] >= F[l]) { 28 | F[l] = F[r] + 1; 29 | succ[i] = ind[r]; 30 | ind[l] = i; 31 | } 32 | } 33 | } 34 | 35 | void print(void) 36 | { unsigned i, bestInd; 37 | 38 | /* Определяне на най-дългата редица */ 39 | bestInd = 0; 40 | for (i = 1; i < BASE; i++) /* Никое число не започва с 0 */ 41 | if (F[i] > F[bestInd]) 42 | bestInd = i; 43 | 44 | /* Извеждане на редицата на екрана */ 45 | printf("\nДължина на максималната домино-подредица: %u", F[bestInd]); 46 | printf("\nЕто и самата подредица: "); 47 | i = ind[bestInd]; 48 | do { 49 | printf("%u ", x[i]); 50 | i = succ[i]; 51 | } while (i > 0); 52 | } 53 | 54 | int main(void) { 55 | solve(); 56 | print(); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /chapter08/fibmatr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define SQR(X) ((X) * (X)) 6 | 7 | const unsigned n = 10; 8 | 9 | unsigned long matrE[2][2] = { { 1, 1 }, { 1, 0 } }; /* Изходна матрица */ 10 | unsigned long matr[2][2]; /* Резултатна матрица */ 11 | 12 | void fibMatr(unsigned n, unsigned long matr[][2]) 13 | { static unsigned long sq12; /* Помощна променлива */ 14 | static unsigned long lMatr[2][2]; /* Помощна матрица */ 15 | 16 | if (n < 2) 17 | memcpy(matr, matrE, 4 * sizeof(matr[0][0])); 18 | else if (0 == n % 2) { 19 | fibMatr(n / 2, lMatr); 20 | sq12 = SQR(lMatr[0][1]); 21 | matr[0][0] = SQR(lMatr[0][0]) + sq12; 22 | matr[1][1] = SQR(lMatr[1][1]) + sq12; 23 | matr[0][1] = matr[0][0] - matr[1][1]; 24 | matr[1][0] = matr[0][1]; 25 | } 26 | else { 27 | fibMatr(n - 1, lMatr); 28 | matr[1][1] = lMatr[0][1]; 29 | matr[0][1] = lMatr[0][0]; 30 | matr[0][0] = lMatr[0][0] + lMatr[1][0]; 31 | matr[1][0] = lMatr[0][1]; 32 | } 33 | } 34 | 35 | int main(void) { 36 | fibMatr(n - 1, matr); 37 | printf("\n%u-тото число на Фибоначи е: %lu", n, matr[0][0]); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /chapter08/fibmemo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 256 5 | 6 | const unsigned n = 10; /* търсим 10-тото число на Фибоначи */ 7 | 8 | unsigned long m[MAX + 1]; 9 | 10 | /* Бърз рекурсивен линеен вариант, запаметяващ вече пресметнатото */ 11 | unsigned long fibMemo(unsigned n) 12 | { if (n < 2) 13 | m[n] = n; 14 | else if (0 == m[n]) 15 | m[n] = fibMemo(n - 1) + fibMemo(n - 2); 16 | return m[n]; 17 | } 18 | 19 | int main(void) { 20 | memset(m, 0, MAX * sizeof(*m)); 21 | printf("\n%u-тото число на Фибоначи е: %lu", n, fibMemo(n)); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /chapter08/fibmemo2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX 250 5 | #define SQR(X) ((X)*(X)) 6 | 7 | unsigned long m[MAX+1]; 8 | 9 | const unsigned n = 10; 10 | 11 | /* Бърз рекурсивен логаритмичен вариант, запаметяващ вече изчисленото */ 12 | unsigned long fMemo2(unsigned n) 13 | { if (n < 2) 14 | m[n] = 1; 15 | else if (0 == m[n]) 16 | if (1 == n % 2) 17 | m[n] = fMemo2(n - 1) + fMemo2(n - 2); 18 | else 19 | m[n] = SQR(fMemo2(n / 2)) + SQR(fMemo2(n / 2 - 1)); 20 | return m[n]; 21 | } 22 | 23 | int main(void) { 24 | memset(m, 0, MAX * sizeof(m[0])); 25 | printf("\n%u-тото число на Фибоначи е: %lu", n, fMemo2(n - 1)); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /chapter08/fibrec.c: -------------------------------------------------------------------------------- 1 | // da oprawq w teksta 2 | // fib(7) dawaha razlichno - da checkna koe e po definiciqta!!! 3 | #include 4 | 5 | const unsigned n = 7; 6 | 7 | unsigned long fib(unsigned n) 8 | { if (n < 2) return 1; 9 | else return fib(n - 1) + fib(n - 2); 10 | } 11 | 12 | int main() { 13 | printf("fib(%u) = %lu\n", n, fib(n)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /chapter08/hedonia.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define MAX 100 5 | #define NOT_CALCULATED 2 6 | 7 | unsigned char F[MAX][MAX]; /* Целева функция */ 8 | 9 | const char *s = "NNNNNNNNECINNxqpCDNNNNNwNNNtNNNNs"; /* Изречение за проверка */ 10 | unsigned n; /* Дължина на изречението */ 11 | 12 | void init(void) 13 | { unsigned i, j; 14 | n = strlen(s); 15 | for (i = 0; i < n; i++) 16 | for (j = 0; j < n; j++) 17 | F[i][j] = NOT_CALCULATED; 18 | } 19 | 20 | unsigned char check(unsigned st, unsigned en) 21 | { unsigned k; 22 | if (NOT_CALCULATED != F[st][en]) 23 | return F[st][en]; 24 | else { 25 | /* Вместо следващите 2 реда */ 26 | if (st == en) 27 | F[st][en] = (s[st] >= 'p' && s[st] <= 'z'); 28 | else if ('N' == s[st]) 29 | F[st][en] = check(st + 1, en); 30 | else if ('C' == s[st] || 'D' == s[st] || 'E' == s[st] || 'I' == s[st]) { 31 | k = st + 1; 32 | while (k < en && !(check(st + 1, k) && check(k + 1, en))) 33 | k++; 34 | F[st][en] = (k != en); 35 | } 36 | else 37 | F[st][en] = 0; 38 | return F[st][en]; 39 | } 40 | } 41 | 42 | int main(void) { 43 | init(); 44 | printf("\nИзречението е %s", check(0, n - 1) ? "правилно!" : "НЕПРАВИЛНО!!!"); 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter08/knapsack2a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define NOT_CALCULATED (unsigned) (-1) 4 | #define MAXN 30 /* Максимален брой предмети */ 5 | #define MAXM 1000 /* Максимална вместимост на раницата */ 6 | 7 | char set[MAXM][MAXN]; /* Множество от предмети за всяко k=1..M */ 8 | unsigned Fn[MAXM]; /* Целева функция */ 9 | 10 | const unsigned m[MAXN] = { 0, 30, 15, 50, 10, 20, 40, 5, 65 }; /* Тегло на предметите */ 11 | const unsigned c[MAXN] = { 0, 5, 3, 9, 1, 2, 7, 1, 12 }; /* Стойност на предметите */ 12 | const unsigned M = 70; /* Обща вместимост на раницата */ 13 | const unsigned N = 8; /* Брой предмети */ 14 | 15 | void calculate(void) 16 | { unsigned maxValue; /* Максимална постигната стойност */ 17 | unsigned maxIndex; /* Индекс, за който е постигната */ 18 | unsigned i, j; 19 | 20 | memset(set, 0, sizeof(set)); /* Инициализиране на множествата с предмети */ 21 | 22 | /* Пресмятане на стойностите на целевата функция */ 23 | for (i = 1; i <= M; i++) { /* Търсим максималната стойност на F(i) */ 24 | maxValue = 0; 25 | maxIndex = 0; 26 | for (j = 1; j <= N; j++) 27 | if (m[j] <= i && !set[i - m[j]][j]) 28 | if (c[j] + Fn[i - m[j]] > maxValue) { 29 | maxValue = c[j] + Fn[i - m[j]]; 30 | maxIndex = j; 31 | } 32 | 33 | if (maxIndex > 0) { /* Съществува ли предмет с тегло, по-малко от i? */ 34 | Fn[i] = maxValue; 35 | 36 | /* Новото множество set[i] се получава от set[i-m[maxIndex]] 37 | * чрез добавяне на елемента maxIndex 38 | */ 39 | memcpy(set[i], set[i - m[maxIndex]], N); 40 | set[i][maxIndex] = 1; 41 | } 42 | 43 | if (Fn[i] < Fn[i - 1]) { /* Раницата побира всички предмети и дори още */ 44 | Fn[i] = Fn[i - 1]; 45 | memcpy(set[i], set[i - 1], N); 46 | } 47 | } 48 | 49 | /* Извеждане на резултата */ 50 | printf("\nВземете предметите с номера:\n"); 51 | for (i = 1; i <= N; i++) 52 | if (set[M][i]) 53 | printf("%5u", i); 54 | printf("\n%s%u", "Максимална постигната ценност: ", Fn[M]); 55 | } 56 | 57 | int main(void) { 58 | printf("%s%u", "\nБрой предмети: ", N); 59 | printf("%s%u", "\nВместимост на раницата: ", M); 60 | calculate(); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /chapter08/knapsack3a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 30 /* Максимален брой предмети */ 3 | #define MAXM 1000 /* Максимална вместимост на раницата */ 4 | 5 | unsigned F[MAXN][MAXM]; /* Целева функция */ 6 | 7 | const unsigned m[MAXN] = {0,1,2,3,5,6,7}; /* Тегло на предметите */ 8 | const unsigned c[MAXN] = {0,1,10,19,22,25,30}; /* Цена на предметите */ 9 | const unsigned M = 15; /* Обща вместимост на раницата */ 10 | const unsigned N = 6; /* Брой предмети */ 11 | 12 | void calculate(void) /* Пресмята стойностите на целевата функция */ 13 | { unsigned i,j; 14 | for (j = 0; j <= M; j++) 15 | F[0][j] = 0; 16 | for (i = 1; i <= N; i++) 17 | for (j = 0; j <= M; j++) 18 | if (j >= m[i] && F[i-1][j] < F[i-1][j-m[i]] + c[i]) 19 | F[i][j] = F[i-1][j-m[i]] + c[i]; 20 | else 21 | F[i][j] = F[i-1][j]; 22 | } 23 | 24 | void printTable(void) /* Извежда съдържанието на таблицата F[i][j] */ 25 | { unsigned i, j; 26 | for (i = 1; i <= N; i++) { 27 | printf("\n"); 28 | for (j = 0; j <= M; j++) 29 | printf("%4u",F[i][j]); 30 | } 31 | } 32 | 33 | void printSet(void) /* Извежда едно възможно множество от предмети, за което */ 34 | { /* се постига максимална стойност на целевата функция */ 35 | unsigned i = N, 36 | j = M; 37 | while (j != 0) { 38 | if (F[i][j] == F[i-1][j]) 39 | i--; 40 | else { 41 | printf("%u ",i); 42 | j -= m[i]; 43 | i--; 44 | } 45 | } 46 | } 47 | 48 | int main(void) 49 | { printf("%s%u","\nБрой предмети: ",N); 50 | printf("%s%u","\nМаксимално допустимо общо тегло: ",M); 51 | calculate(); 52 | printf("\nТаблица F[i][j]: "); 53 | printTable(); 54 | printf("\n%s%u","Максимална постигната стойност: ",F[N][M]); 55 | printf("\nВземете предметите с номера: "); printSet(); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /chapter08/knapsack3b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 30 /* Максимален брой предмети */ 3 | #define MAXM 1000 /* Максимална вместимост на раницата */ 4 | 5 | unsigned F[MAXN][MAXM]; /* Целева функция */ 6 | 7 | const unsigned m[MAXN] = {0,6,3,10,2,4,8,1,13,3}; /* Тегло на предметите */ 8 | const unsigned c[MAXN] = {0,5,3,9,1,2,7,1,12,3}; /* Цена на предметите */ 9 | const unsigned M = 14; /* Обща вместимост на раницата */ 10 | const unsigned N = 9; /* Брой предмети */ 11 | 12 | void calculate(void) /* Пресмята стойностите на целевата функция */ 13 | { unsigned i,j; 14 | for (j = 0; j <= M; j++) 15 | F[0][j] = 0; 16 | for (i = 1; i <= N; i++) 17 | for (j = 0; j <= M; j++) 18 | if (j >= m[i] && F[i-1][j] < F[i-1][j-m[i]] + c[i]) 19 | F[i][j] = F[i-1][j-m[i]] + c[i]; 20 | else 21 | F[i][j] = F[i-1][j]; 22 | } 23 | 24 | void printTable(void) /* Извежда съдържанието на таблицата F[i][j] */ 25 | { unsigned i, j; 26 | for (i = 1; i <= N; i++) { 27 | printf("\n"); 28 | for (j = 0; j <= M; j++) 29 | printf("%4u",F[i][j]); 30 | } 31 | } 32 | 33 | unsigned set[MAXN]; /* Множество от предмети, за които се постига max */ 34 | 35 | void printAll(unsigned i, unsigned j, unsigned k) 36 | { /* Извежда ВСИЧКИ възможни множества от предмети, за които */ 37 | /* се постига максимална стойност на целевата функция */ 38 | if (0 == j) { 39 | printf("\nВземете следните предмети: "); 40 | for (i = 0; i < k; i++) 41 | printf("%u ",set[i]); 42 | } 43 | else { 44 | if (F[i][j] == F[i-1][j]) 45 | printAll(i-1,j,k); 46 | if (j >= m[i] && F[i][j] == F[i-1][j-m[i]] + c[i]) { 47 | set[k] = i; 48 | printAll(i-1,j-m[i],k+1); 49 | } 50 | } 51 | } 52 | 53 | int main(void) { 54 | printf("%s%u","\nБрой предмети: ",N); 55 | printf("%s%u","\nМаксимална допустима обща маса: ",M); 56 | calculate(); 57 | printf("\nТаблица F[i][j]: "); 58 | printTable(); 59 | printf("\n%s%u","Максимална постигната стойност: ",F[N][M]); 60 | printf("\nСледват всевъзможните множества от решения:"); 61 | printAll(N,M,0); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /chapter08/knapsack3c.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 30 /* Максимален брой предмети */ 3 | #define MAXM 1000 /* Максимална вместимост на раницата */ 4 | 5 | const unsigned m[MAXN] = {0,1,2,3,5,6,7}; /* Тегло на предметите */ 6 | const unsigned c[MAXN] = {0,1,10,19,22,25,30}; /* Стойност на предметите */ 7 | const unsigned M = 15; /* Обща вместимост на раницата */ 8 | const unsigned N = 6; /* Брой предмети */ 9 | 10 | unsigned calculate(void) /* Пресмята стойностите на целевата функция */ 11 | { unsigned F[MAXM], OldF[MAXM]; /* Целева функция */ 12 | unsigned i,j,k; 13 | 14 | for (j = 0; j <= M; j++) 15 | OldF[j] = 0; 16 | for (i = 1; i <= N; i++) { 17 | for (j = 0; j <= M; j++) 18 | if (j >= m[i] && OldF[j] < OldF[j-m[i]] + c[i]) 19 | F[j] = OldF[j-m[i]] + c[i]; 20 | else F[j] = OldF[j]; 21 | for (k = 0; k < M; k++) 22 | OldF[k] = F[k]; 23 | } 24 | return F[M]; 25 | } 26 | 27 | int main(void) { 28 | printf("%s%u","\nБрой предмети: ",N); 29 | printf("%s%u","\nМаксимална допустима обща маса: ",M); 30 | printf("\n%s%u","Максимална постигната ценност: ",calculate()); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /chapter08/knapsack4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 30 /* Максимален брой предмети */ 3 | #define MAXM 1000 /* Максимална вместимост на раницата */ 4 | 5 | unsigned F[MAXM]; /* Целева функция */ 6 | unsigned best[MAXM]; /* Последен добавен предмет при достигане на максимума */ 7 | 8 | const unsigned m[MAXN] = {0,30,15,50,10,20,40,5,65}; /* Тегло на предметите */ 9 | const unsigned c[MAXN] = {0,5,3,9,1,2,7,1,12}; /* Стойност на предметите */ 10 | const unsigned M = 70; /* Обща вместимост на раницата */ 11 | const unsigned N = 8; /* Брой предмети */ 12 | 13 | void calculate(void) /* Пресмята стойностите на целевата функция */ 14 | { unsigned i,j; 15 | 16 | /* Инициализация */ 17 | for (i = 0; i <= M; i++) 18 | F[i] = 0; 19 | 20 | /* Основен цикъл */ 21 | for (j = 1; j <= N; j++) 22 | for (i = 1; i <= M; i++) 23 | if (i >= m[j]) 24 | if (F[i] < F[i-m[j]] + c[j]) { 25 | F[i] = F[i-m[j]] + c[j]; 26 | best[i] = j; 27 | } 28 | } 29 | 30 | void printSet(void) /* Извежда едно възможно множество от предмети, за което */ 31 | { /* се постига максимална стойност на целевата функция */ 32 | unsigned value = M; 33 | printf("\nВземете следните предмети: "); 34 | while (value) { 35 | printf("%4u ", best[value]); 36 | value -= m[best[value]]; 37 | } 38 | } 39 | 40 | int main(void) { 41 | printf("%s%u","\nБрой предмети: ",N); 42 | printf("%s%u","\nМаксимална допустима обща маса: ",M); 43 | calculate(); 44 | printf("\n%s%u","Максимална постигната стойност: ",F[M]); 45 | printSet(); 46 | return 0; 47 | } -------------------------------------------------------------------------------- /chapter08/knapsack5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 30 /* Максимален брой предмети */ 3 | #define MAXM 1000 /* Максимална вместимост на раницата */ 4 | 5 | unsigned F[MAXM]; /* Целева функция */ 6 | unsigned best[MAXM]; /* Последен добавен предмет при достигане на максимума */ 7 | 8 | const unsigned m[MAXN] = {0,30,15,50,10,20,40,5,65}; /* Тегло на предметите */ 9 | const unsigned c[MAXN] = {0,5,3,9,1,2,7,1,12}; /* Стойност на предметите */ 10 | const unsigned M = 70; /* Обща вместимост на раницата */ 11 | const unsigned N = 8; /* Брой предмети */ 12 | 13 | char used(unsigned i, unsign/ed j) 14 | { /* Проверява дали j участва в оптималното множество, определено от F[i] */ 15 | while (i != 0 && best[i] != 0) 16 | if (best[i] == j) 17 | return 1; 18 | else 19 | i -= m[best[i]]; 20 | return 0; 21 | } 22 | 23 | void calculate() /* Пресмята стойностите на целевата функция */ 24 | { unsigned i,j; 25 | 26 | /* Инициализация */ 27 | for (i = 0; i <= M; i++) 28 | best[i] = 0; 29 | 30 | /* Основен цикъл */ 31 | for (i = 1; i <= M; i++) 32 | for (j = 1; j <= N; j++) 33 | if (i >= m[j]) 34 | if (F[i] < F[i-m[j]] + c[j]) 35 | if (!used(i-m[j],j)) { 36 | F[i] = F[i-m[j]] + c[j]; 37 | best[i] = j; 38 | } 39 | } 40 | 41 | void printSet() /* Извежда едно възможно множество от предмети, за което */ 42 | { /* се постига максимална стойност на целевата функция */ 43 | unsigned value = M; 44 | while (value) { 45 | printf("%4u ",best[value]); 46 | value -= m[best[value]]; 47 | } 48 | } 49 | 50 | int main() { 51 | printf("\nБрой предмети: %u",N); 52 | printf("\nМаксимална допустима обща маса: %u",M); 53 | calculate(); 54 | printf("\nМаксимална постигната ценност: %u",F[M]); 55 | printf("\nВземете следните предмети: "); printSet(); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /chapter08/lcs1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAXN 100 4 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /* Връща по-големия аргумент */ 5 | 6 | char F[MAXN][MAXN]; /* Целева функция */ 7 | 8 | const char x[MAXN] = "acbcacbcaba"; /* Първа редица */ 9 | const char y[MAXN] = "abacacacababa"; /* Втора редица */ 10 | 11 | /* Намира дължината на най-дългата обща подредица */ 12 | unsigned LCS_Length(void) 13 | { unsigned i, j, m, n; 14 | m = strlen(x); /* Дължина на първата редица */ 15 | n = strlen(y); /* Дължина на втората редица */ 16 | /* Начална инициализация */ 17 | for (i = 1; i <= m; i++) 18 | F[i][0] = 0; 19 | for (j = 0; j <= n; j++) 20 | F[0][j] = 0; 21 | /* Основен цикъл */ 22 | for (i = 1; i <= m; i++) 23 | for (j = 1; j <= n; j++) 24 | if (x[i - 1] == y[j - 1]) 25 | F[i][j] = F[i - 1][j - 1] + 1; 26 | else 27 | F[i][j] = MAX(F[i - 1][j], F[i][j - 1]); 28 | return F[m][n]; 29 | } 30 | 31 | int main(void) { 32 | printf("\nДължина на най-дългата обща подредица: %u", LCS_Length()); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /chapter08/lns1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | const int x[MAX] = {100, 10, 15, 5, 25, 22, 12, 22}; /* Редица */ 5 | /* Нулевият елемент на x[] не се използва! */ 6 | const unsigned n = 7; /* Брой елементи в редицата */ 7 | int LNS[MAX][MAX]; /* Целева функция */ 8 | 9 | /* Намира дължината на най-дългата ненамаляваща подредица */ 10 | unsigned LNS_Length(void) 11 | { unsigned i, j, r; 12 | 13 | /* Начална инициализация */ 14 | for (i = 0; i <= n; i++) { 15 | for (j = 1; j <= n; j++) 16 | LNS[i][j] = MAX + 1; 17 | LNS[i][0] = -1; 18 | } 19 | 20 | /* Основен цикъл */ 21 | r = 1; 22 | for (i = 1; i <= n; i++) { 23 | for (j = 1; j <= n; j++) { 24 | if (LNS[i - 1][j - 1] <= x[i] && x[i] <= LNS[i - 1][j] 25 | && LNS[i - 1][j - 1] <= LNS[i - 1][j]) { 26 | LNS[i][j] = x[i]; 27 | if (r < j) 28 | r = j; 29 | } 30 | else 31 | LNS[i][j] = LNS[i - 1][j]; 32 | } 33 | } 34 | 35 | return r; 36 | } 37 | 38 | /* Извежда най-дългата ненамаляваща подредица (в обратен ред) */ 39 | void LNS_Print(unsigned j) 40 | { unsigned i = n; 41 | do { 42 | if (LNS[i][j] == LNS[i - 1][j]) 43 | i--; 44 | else { 45 | printf("%d ", x[i]); 46 | j--; 47 | } 48 | } while (i > 0); 49 | } 50 | 51 | /* Извежда най-дългата ненамаляваща подредица */ 52 | void LNS_Print2(unsigned i, unsigned j) 53 | { if (0 == i) return; 54 | if (LNS[i][j] == LNS[i - 1][j]) 55 | LNS_Print2(i - 1, j); 56 | else { 57 | LNS_Print2(i, j - 1); 58 | printf("%d ", x[i]); 59 | } 60 | } 61 | 62 | int main(void) { 63 | unsigned len = LNS_Length(); 64 | printf("\nДължина на най-дългата ненамаляваща подредица: %u", len); 65 | printf("\nПодредицата (обърната): "); LNS_Print(len); 66 | printf("\nПодредицата: "); LNS_Print2(n, len); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /chapter08/lns2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | const int x[MAX] = {100, 10, 15, 5, 25, 22, 12, 22}; /* Редица */ 5 | /* Нулевият елемент на x[] не се използва! */ 6 | const unsigned n = 7; /* Брой елементи в редицата */ 7 | 8 | unsigned LNS[MAX]; /* Дължина на максималната редица с начало x[i] */ 9 | unsigned next[MAX]; /* Индекс на следващ елемент */ 10 | 11 | /* Намира дължината на най-дългата ненамаляваща подредица */ 12 | unsigned LNS_Length(unsigned *start) 13 | { unsigned i, j; 14 | unsigned l; /* В момента на разглеждане на xi, 15 | /* l е дължината на максималната подредица с начало xj: */ 16 | /* 1) i < j <= n и */ 17 | /* 2) xi <= xj */ 18 | unsigned len = 0; /* Максимална (за момента) дължина на ненамаляваща подредица */ 19 | for (i = n; i >= 1; i--) { 20 | for (l = 0, j = i + 1; j <= n; j++) 21 | if (x[j] >= x[i] && LNS[j] > l) { 22 | l = LNS[j]; 23 | next[i] = j; 24 | } 25 | LNS[i] = l + 1; 26 | if (LNS[i] > len) { 27 | len = LNS[i]; 28 | *start = i; 29 | } 30 | } 31 | return len; 32 | } 33 | 34 | /* Извежда най-дългата ненамаляваща подредица */ 35 | void LNS_Print(unsigned start) 36 | { for (; LNS[start] >= 1; start = next[start]) 37 | printf(" %d", x[start]); 38 | } 39 | 40 | int main(void) { 41 | unsigned start; 42 | printf("Дължина на най-дългата ненамаляваща подредица: %u\n", LNS_Length(&start)); 43 | printf("Подредицата: "); LNS_Print(start); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /chapter08/lns3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | 4 | const int x[MAX] = {100, 10, 15, 5, 25, 22, 12, 22}; /* Редица */ 5 | /* Нулевият елемент на x[] не се използва! */ 6 | const unsigned n = 7; /* Брой елементи в редицата */ 7 | int LNS[MAX]; /* LNS[i] - минимален елемент, който може да стои на позиция i */ 8 | 9 | /* Намира дължината на най-дългата ненамаляваща подредица */ 10 | unsigned LNS_Length(void) 11 | { unsigned i, r, k, l, med; 12 | 13 | for (LNS[1] = x[1], k = 1, i = 2; i <= n; i++) { 14 | if (x[i] < LNS[1]) /* случай 1 */ 15 | LNS[1] = x[i]; 16 | else if (x[i] >= LNS[k]) /* случай 2 */ 17 | LNS[++k] = x[i]; 18 | else { /* случай 3 */ 19 | l = 1; 20 | r = k; /* двоично търсене */ 21 | while (l < r - 1) { 22 | med = (l + r) / 2; 23 | if (LNS[med] <= x[i]) 24 | l = med; 25 | else 26 | r = med; 27 | } 28 | LNS[r] = x[i]; 29 | } 30 | } 31 | return k; 32 | } 33 | 34 | int main(void) { 35 | printf("Дължина на най-дългата ненамаляваща подредица: %u\n", LNS_Length()); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /chapter08/matrix1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | #define INFINITY (unsigned long)(-1) 4 | 5 | unsigned long m[MAX][MAX]; /* Таблица - целева функция */ 6 | 7 | const unsigned long r[MAX+1] = {12,13,35,3,34,2,21,10,21,6}; /* Размерности на матриците */ 8 | const unsigned n = 9; /* Брой матрици */ 9 | 10 | /* Неефективна рекурсивна функция */ 11 | unsigned long solveRecursive(unsigned i, unsigned j) 12 | { unsigned k; 13 | if (i == j) return 0; 14 | m[i][j] = INFINITY; 15 | for (k = i; k <= j - 1; k++) { 16 | unsigned long q = solveRecursive(i, k) + 17 | solveRecursive(k + 1, j) + 18 | r[i - 1] * 19 | r[k] * 20 | r[j]; 21 | if (q < m[i][j]) 22 | m[i][j] = q; 23 | } 24 | 25 | return m[i][j]; 26 | } 27 | 28 | void printMatrix(void) /* Извежда матрицата на минимумите на екрана */ 29 | { unsigned i,j; 30 | printf("\nМатрица на минимумите:"); 31 | for (i = 1; i <= n; i++) { 32 | printf("\n"); 33 | for (j = 1; j <= n; j++) 34 | printf("%8lu", m[i][j]); 35 | } 36 | } 37 | 38 | int main(void) { 39 | printf("\nМинималният брой умножения е: %lu",solveRecursive(1,n)); 40 | printMatrix(); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /chapter08/matrix2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | #define NOT_SOLVED (unsigned long)(-1) 4 | 5 | unsigned long m[MAX][MAX]; /* Таблица - целева функция */ 6 | 7 | const unsigned long r[MAX+1] = {12,13,35,3,34,2,21,10,21,6}; /* Размерности на матриците */ 8 | const unsigned n = 9; /* Брой матрици */ 9 | 10 | long solveMemo(unsigned i, unsigned j) 11 | { unsigned k; 12 | unsigned long q; 13 | if (NOT_SOLVED != m[i][j]) /* Стойността вече е била пресметната */ 14 | return m[i][j]; 15 | if (i == j) /* В този интервал няма матрица */ 16 | m[i][j] = 0; 17 | else { /* Пресмятаме рекурсивно */ 18 | for (k = i; k <= j - 1; k++) 19 | if ((q = solveMemo(i, k) + solveMemo(k + 1, j) + r[i-1] * r[k] * r[j]) < m[i][j]) 20 | m[i][j] = q; 21 | } 22 | return m[i][j]; 23 | } 24 | 25 | long solveMemoization(void) 26 | { unsigned i, j; 27 | for (i = 1; i <= n; i++) 28 | for (j = i; j <= n; j++) 29 | m[i][j] = NOT_SOLVED; 30 | return solveMemo(1, n); 31 | } 32 | 33 | void printMatrix(void) /* Извежда матрицата на минимумите на екрана */ 34 | { unsigned i,j; 35 | printf("\nМатрица на минимумите:"); 36 | for (i = 1; i <= n; i++) { 37 | printf("\n"); 38 | for (j = 1; j <= n; j++) 39 | printf("%8lu", m[i][j]); 40 | } 41 | } 42 | 43 | int main(void) { 44 | printf("\nМинималният брой умножения е: %lu", solveMemoization()); 45 | printMatrix(); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /chapter08/no2zero.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | #define NOT_SOLVED (unsigned long)(-1) 4 | 5 | unsigned long F[MAX]; /* Целева функция */ 6 | unsigned long pow[MAX]; /* Степените на k */ 7 | 8 | const unsigned n = 10; 9 | const unsigned k = 7; 10 | 11 | void init(void) 12 | { unsigned i; 13 | for (i = pow[0] = 1; i <= n; i++) { 14 | pow[i] = k * pow[i - 1]; 15 | F[i] = NOT_SOLVED; 16 | } 17 | } 18 | 19 | unsigned long solve(unsigned s) 20 | { unsigned i; 21 | if (NOT_SOLVED == F[s]) { 22 | F[s] = pow[s - 2]; 23 | for (i = 1; i < s - 1; i++) 24 | F[s] += solve(i - 1) * (k - 1) * pow[s - i - 2]; 25 | F[s] = pow[s] - F[s]; 26 | } 27 | return F[s]; 28 | } 29 | 30 | int main(void) { 31 | init(); 32 | F[0] = 1; F[1] = k; F[2] = k * k - 1; 33 | printf("%lu\n", (k - 1) * solve(n - 1)); 34 | return 0; 35 | } -------------------------------------------------------------------------------- /chapter08/partitio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 80 3 | #define INFINITY (unsigned long)(-1) 4 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /* Връща по-големия аргумент */ 5 | 6 | unsigned long p[MAXN]; /* Префиксни суми */ 7 | unsigned long F[MAXN][MAXN]; /* Целева функция */ 8 | unsigned long b[MAXN][MAXN]; /* За възстановяване на решението */ 9 | 10 | const unsigned s[MAXN] = {0,23,15,89,170,25,1,86,80,2,27}; /* Редица (нулевият елемент не се ползва) */ 11 | const unsigned n = 10; /* Брой елементи в редицата */ 12 | const unsigned k = 4; /* Брой групи */ 13 | 14 | /* Извършва оптимално разделяне на k групи */ 15 | long doPartition(unsigned k) 16 | { unsigned i, j, l, m; 17 | /* Пресмятане на префиксните суми */ 18 | for (p[0] = 0, i = 1; i <= n; i++) 19 | p[i] = p[i - 1] + s[i]; 20 | /* Установяване на граничните условия */ 21 | for (i = 1; i <= n; i++) 22 | F[i][1] = p[i]; 23 | for (j = 1; j <= k; j++) 24 | F[1][j] = s[1]; 25 | /* Основен цикъл */ 26 | for (i = 2; i <= n; i++) 27 | for (j = 2; j <= k; j++) 28 | for (F[i][j] = INFINITY, l = 1; l <= i - 1; l++) 29 | if ((m = MAX(F[l][j - 1], p[i] - p[l])) < F[i][j]) { 30 | F[i][j] = m; 31 | b[i][j] = l; 32 | } 33 | return F[n][k]; 34 | } 35 | 36 | void print(unsigned from, unsigned to) 37 | { unsigned i; 38 | printf("\n"); 39 | for (i = from; i <= to; i++) 40 | printf("%u ", s[i]); 41 | } 42 | 43 | void printPartition(unsigned n, unsigned k) 44 | { if (1 == k) 45 | print(1, n); 46 | else { 47 | printPartition(b[n][k], k - 1); 48 | print(b[n][k] + 1, n); 49 | } 50 | } 51 | 52 | int main(void) { 53 | printf("\nМаксимална сума в някоя от групите: %lu", doPartition(k)); 54 | printPartition(n, k); 55 | return 0; 56 | } -------------------------------------------------------------------------------- /chapter08/railway.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 8000 3 | #define NOT_CALCULATED (unsigned long)(-1) 4 | 5 | unsigned long minPrice[MAX]; /* Минимална цена на билета от началната до текущата гара */ 6 | 7 | const unsigned long dist[MAX] = {0,3,7,8,13,15,23}; /* Разстояние от началната гара */ 8 | const unsigned long l1 = 3, l2 = 6, l3 = 8, 9 | c1 = 20, c2 = 30, c3 = 40; 10 | const unsigned n = 7; 11 | const unsigned end = 6; 12 | unsigned start = 2; 13 | 14 | unsigned long calc(unsigned cur) 15 | { unsigned i; 16 | unsigned long price; 17 | if (NOT_CALCULATED == minPrice[cur]) { 18 | /* Търсим най-лявата гара и пресмятаме евентуалната цена, ако вземем билет тип 1 */ 19 | for (i = cur - 1; i >= start && (dist[cur] - dist[i]) <= l1; i--); 20 | if (++i < cur) 21 | if ((price = calc(i) + c1) < minPrice[cur]) 22 | minPrice[cur] = price; 23 | /* Търсим най-лявата гара и пресмятаме евентуалната цена, ако вземем билет тип 2 */ 24 | for (; i >= start && (dist[cur] - dist[i]) <= l2; i--); 25 | if (++i < cur) 26 | if ((price = calc(i) + c2) < minPrice[cur]) minPrice[cur] = price; 27 | /* Търсим най-лявата гара и пресмятаме евентуалната цена, ако вземем билет тип 3 */ 28 | for (; i >= start && (dist[cur] - dist[i]) <= l3; i--); 29 | if (++i < cur) 30 | if ((price = calc(i) + c3) < minPrice[cur]) minPrice[cur] = price; 31 | } 32 | return minPrice[cur]; 33 | } 34 | 35 | int main(void) { 36 | unsigned i; 37 | /* Иницализация */ 38 | for (i = 0; i < start; i++) 39 | minPrice[i] = 0; 40 | for (; i < n; i++) 41 | minPrice[i] = NOT_CALCULATED; 42 | /* Решаване на задачата */ 43 | start--; 44 | printf("Минимална цена: %lu\n", calc(end-1)); 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter08/relation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define NOT_CALCULATED (unsigned char)(-1) 4 | #define MAXSLEN 100 /* Максимална дължина на низа */ 5 | #define LETTS 3 /* Брой букви */ 6 | /* Таблица на умножение */ 7 | char rel[LETTS][LETTS] = { 8 | { 'b', 'b', 'a' }, 9 | { 'c', 'b', 'a' }, 10 | { 'a', 'c', 'c' }}; 11 | char *s = "bacacbcabbbcacab"; 12 | 13 | unsigned char table[MAXSLEN][MAXSLEN][LETTS]; 14 | unsigned char split[MAXSLEN][MAXSLEN]; 15 | 16 | unsigned char can(unsigned char i, unsigned char j, unsigned char ch) 17 | { unsigned char c1, c2, pos; 18 | if (table[i][j][ch] != NOT_CALCULATED) 19 | return table[i][j][ch]; /* Вече сметнато */ 20 | if (i == j) 21 | return(s[i] == ch + 'a'); 22 | for (c1 = 0; c1 < LETTS; c1++) 23 | for (c2 = 0; c2 < LETTS; c2++) 24 | if (rel[c1][c2] == ch + 'a') 25 | for (pos = i; pos <= j - 1; pos++) 26 | if (can(i, pos, c1)) 27 | if (can(pos + 1, j, c2)) { 28 | table[i][j][ch] = 1; 29 | split[i][j] = pos; 30 | return 1; 31 | } 32 | table[i][j][ch] = 0; 33 | return 0; 34 | } 35 | 36 | void putBrackets(unsigned char i, unsigned char j) 37 | { /* Поставя скобите с израза */ 38 | if (i == j) 39 | printf("%c", s[i]); 40 | else { 41 | printf("("); 42 | putBrackets(i, split[i][j]); 43 | printf("*"); 44 | putBrackets(split[i][j] + 1, j); 45 | printf(")"); 46 | } 47 | } 48 | 49 | int main(void) { 50 | unsigned char len = strlen(s); 51 | memset(table, NOT_CALCULATED, sizeof(table)); 52 | if (can(0, len - 1, 0)) 53 | putBrackets(0, len - 1); 54 | else 55 | printf("Няма решение"); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /chapter08/series.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const float p = 0.5; /* Вероятност A да спечели отделен мач */ 4 | const unsigned n = 5; 5 | 6 | /* Неефективен рекурсивен вариант */ 7 | float P(unsigned i, unsigned j) 8 | { if (0 == j) 9 | return 0.0; 10 | else if (0 == i) 11 | return 1.0; 12 | else 13 | return p * P(i - 1, j) + (1 - p) * P(i, j - 1); 14 | } 15 | 16 | int main(void) { 17 | unsigned i, j; 18 | for (i = 0; i < n; i++) { 19 | for (j = 0; j < n; j++) 20 | printf("%f ", P(i,j)); 21 | printf("\n"); 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /chapter08/series2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX 100 4 | #define q (1 - (p)) /* Вероятност B да спечели отделен мач */ 5 | 6 | const float p = 0.5; /* Вероятност A да спечели отделен мач */ 7 | const unsigned n = 5; 8 | 9 | struct { 10 | char calculated; /* Пресметната ли е вече стойността? */ 11 | float value; /* Пресметната стойност */ 12 | } PS[MAX][MAX]; 13 | 14 | float pDyn(unsigned i, unsigned j) /* Динамично оптимиране */ 15 | { if (!PS[i][j].calculated) { 16 | PS[i][j].value = p * pDyn(i - 1, j) + q * pDyn(i, j - 1); 17 | PS[i][j].calculated = 1; 18 | } 19 | return PS[i][j].value; 20 | } 21 | 22 | float pDynamic(unsigned i, unsigned j) 23 | { unsigned k, l; 24 | for (k = 1; k <= i; k++) 25 | for (l = 1; l <= j; l++) 26 | PS[k][l].calculated = 0; 27 | for (k = 1; k <= i; k++) { 28 | PS[0][k].value = 1.0; 29 | PS[0][k].calculated = 1; 30 | } 31 | for (k = 1; k <= j; k++) { 32 | PS[k][0].value = 0.0; 33 | PS[k][0].calculated = 1; 34 | } 35 | return pDyn(i, j); 36 | } 37 | 38 | int main(void) { 39 | unsigned i, j; 40 | pDynamic(n,n); 41 | for (i = 0; i < n; i++) { 42 | for (j = 0; j < n; j++) 43 | printf("%f ", PS[i][j].value); 44 | printf("\n"); 45 | } 46 | return 0; 47 | } -------------------------------------------------------------------------------- /chapter08/series3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX 100 4 | #define NOT_CALCULATED (-1) 5 | #define q (1 - (p)) /* Вероятност B да спечели отделен мач */ 6 | const float p = 0.5; /* Вероятност A да спечели отделен мач */ 7 | const unsigned n = 5; 8 | 9 | float PS[MAX][MAX]; 10 | 11 | float pDyn(unsigned i, unsigned j) /* Динамично оптимиране */ 12 | { if (PS[i][j] < 0) 13 | PS[i][j] = p * pDyn(i - 1, j) + q * pDyn(i, j - 1); 14 | return PS[i][j]; 15 | } 16 | 17 | float pDynamic2(unsigned i, unsigned j) 18 | { unsigned k, l; 19 | for (k = 1; k <= i; k++) 20 | for (l = 1; l <= j; l++) 21 | PS[k][l] = NOT_CALCULATED; 22 | for (k = 1; k <= i; k++) 23 | PS[k][0] = 0.0; 24 | for (k = 1; k <= j; k++) 25 | PS[0][k] = 1.0; 26 | 27 | return pDyn(i, j); 28 | } 29 | 30 | int main(void) { 31 | unsigned i, j; 32 | pDynamic2(n,n); 33 | for (i = 0; i < n; i++) { 34 | for (j = 0; j < n; j++) 35 | printf("%f ", PS[i][j]); 36 | printf("\n"); 37 | } 38 | return 0; 39 | } -------------------------------------------------------------------------------- /chapter08/series4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX 100 4 | #define q (1 - (p)) /* Вероятност B да спечели отделен мач */ 5 | const float p = 0.5; /* Вероятност A да спечели отделен мач */ 6 | const unsigned n = 5; 7 | 8 | float pDynamic3(unsigned i, unsigned j) 9 | { float P[MAX][MAX]; 10 | unsigned s, k; 11 | P[0][0] = 0.0; /* Това е излишно. Не ни трябва */ 12 | for (s = 1; s <= i + j; s++) { 13 | P[0][s] = 1.0; 14 | P[s][0] = 0.0; 15 | for (k = 1; k <= s - 1; k++) 16 | P[k][s - k] = p * P[k - 1][s - k] + q * P[k][s - k - 1]; 17 | } 18 | return P[i][j]; 19 | } 20 | 21 | int main(void) { 22 | unsigned i, j; 23 | for (i = 0; i < n; i++) { 24 | for (j = 0; j < n; j++) 25 | printf("%f ", pDynamic3(i,j)); 26 | printf("\n"); 27 | } 28 | return 0; 29 | } -------------------------------------------------------------------------------- /chapter08/taxi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 100 /* Максимален брой километри */ 3 | #define MAXK 20 /* Максимален брой спирки */ 4 | #define INFINITY (unsigned)(-1) 5 | 6 | struct { 7 | unsigned last; /* Последна измината отсечка */ 8 | unsigned value; /* Цена на разстоянието */ 9 | } dist[MAXN]; 10 | 11 | const unsigned values[MAXK+1] = {0,12,21,31,40,49,58,69,79,90,101}; 12 | const unsigned n = 15; 13 | const unsigned k = 10; 14 | 15 | void solve(unsigned n) /* Решава задачата чрез динамично оптимиране */ 16 | { unsigned i, j; 17 | dist[0].value = 0; 18 | for (i = 1; i <= n; i++) { 19 | dist[i].value = INFINITY; 20 | for (j = 1; j <= k && j <= i; j++) 21 | if (dist[i - j].value + values[j] < dist[i].value) { 22 | dist[i].value = dist[i - j].value + values[j]; 23 | dist[i].last = j; 24 | } 25 | } 26 | } 27 | 28 | void print(unsigned n) /* Извежда резултата на екрана */ 29 | { printf("\n%s%u", "Обща стойност на пътуването: ", dist[n].value); 30 | printf("\nДължина и стойности на отделните отсечки:"); 31 | while (n > 0) { 32 | printf("\n%u %u", dist[n].last, values[dist[n].last]); 33 | n -= dist[n].last; 34 | } 35 | } 36 | 37 | int main(void) { 38 | solve(n); 39 | print(n); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /chapter08/tickets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXN 1000 3 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 4 | 5 | unsigned F[MAXN]; /* Целева функция */ 6 | 7 | const unsigned T[MAXN] = {8,5,3,9,2,1,4,4,1,17}; /* Време за обслужване на един фен */ 8 | const unsigned R[MAXN] = {1,3,9,4,2,4,9,3,8}; /* Време за обслужване на двойка фенове */ 9 | unsigned n = 10; /* Брой фенове */ 10 | 11 | /* Пресмята стойностите на целевата функция */ 12 | void solve(void) 13 | { unsigned i; 14 | F[0] = 0; F[1] = T[0]; 15 | for (i = 2; i <= n; i++) 16 | F[i] = MIN(F[i - 1] + T[i - 1], F[i - 2] + R[i - 2]); 17 | } 18 | 19 | /* Извежда решението на екрана */ 20 | void print(void) 21 | { printf("\nМинимално време за обслужване на опашката: %u", F[n]); 22 | do 23 | if (F[n - 1] + T[n - 1] == F[n]) 24 | printf("\n%u", n--); 25 | else { 26 | printf("\n(%u,%u)", n - 1, n); 27 | n -= 2; 28 | } 29 | while (n > 0); 30 | } 31 | 32 | int main(void) { 33 | solve(); 34 | print(); 35 | return 0; 36 | } -------------------------------------------------------------------------------- /chapter08/transform.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 100 4 | #define COST_DELETE 1 5 | #define COST_INSERT 2 6 | #define COST_REPLACE(i, j) ((s1[i] == s2[j]) ? 0 : 3) 7 | #define min2(a, b) ((a < b) ? a : b) /* Връща по-малкия от 2 аргумента */ 8 | #define min(a, b, c) min2(min2(a, b), c) /* Връща най-малкия от 3 аргумента */ 9 | 10 | unsigned F[MAX+1][MAX+1]; /* Целева функция */ 11 | unsigned n1; /* Дължина на първия низ */ 12 | unsigned n2; /* Дължина на втория низ */ 13 | 14 | const char *s1 = "_abracadabra"; /* Изходен низ (първият символ няма значение) */ 15 | const char *s2 = "_mabragabra"; /* Низ-цел (първият символ няма значение) */ 16 | 17 | /* Намира разстоянието между два низа */ 18 | unsigned editDistance(void) 19 | { unsigned i, j; 20 | /* Инициализация */ 21 | for (i = 0; i <= n1; i++) 22 | F[i][0] = i * COST_DELETE; 23 | for (j = 0; j <= n2; j++) 24 | F[0][j] = j * COST_INSERT; 25 | /* Основен цикъл */ 26 | for (i = 1; i <= n1; i++) 27 | for (j = 1; j <= n2; j++) 28 | F[i][j] = min(F[i - 1][j - 1] + COST_REPLACE(i, j), 29 | F[i][j - 1] + COST_INSERT, 30 | F[i - 1][j] + COST_DELETE); 31 | return F[n1][n2]; 32 | } 33 | 34 | /* Извежда операциите по редактирането */ 35 | void printEditOperations(unsigned i, unsigned j) 36 | { 37 | if (0 == j) 38 | for (j = 1; j <= i; j++) 39 | printf("DELETE(%u) ", j); 40 | else if (0 == i) 41 | for (i = 1; i <= j; i++) 42 | printf("INSERT(%u,%c) ", i, s2[i]); 43 | else if (i > 0 && j > 0) { 44 | if (F[i][j] == F[i - 1][j - 1] + COST_REPLACE(i, j)) { 45 | printEditOperations(i - 1, j - 1); 46 | if (COST_REPLACE(i, j) > 0) 47 | printf("REPLACE(%u,%c) ", i, s2[j]); 48 | } 49 | else if (F[i][j] == F[i][j - 1] + COST_INSERT) { 50 | printEditOperations(i, j - 1); 51 | printf("INSERT(%u,%c) ", i, s2[j]); 52 | } 53 | else if (F[i][j] == F[i - 1][j] + COST_DELETE) { 54 | printEditOperations(i - 1, j); 55 | printf("DELETE(%u) ", i); 56 | } 57 | } 58 | } 59 | 60 | int main(void) { 61 | n1 = strlen(s1) - 1; 62 | n2 = strlen(s2) - 1; 63 | printf("\nМинимално разстояние между двата низа: %u\n", editDistance()); 64 | printEditOperations(n1, n2); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /chapter08/tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | #define INFINITY (unsigned long)(-1) 4 | 5 | unsigned long m[MAX][MAX]; /* Таблица - целева функция */ 6 | 7 | const unsigned long f[MAX+1] = {2,7,1,3,4,6,5}; /* Честоти на срещане */ 8 | const unsigned n = 7; /* Брой честоти */ 9 | 10 | /* Построява оптимално двоично дърво за претърсване */ 11 | void solve(void) 12 | { unsigned i, j, k; 13 | unsigned long t; 14 | 15 | /* Инициализация */ 16 | for (i = 1; i <= n; i++) { 17 | m[i][i] = f[i-1]; 18 | m[i][i-1] = 0; 19 | } 20 | m[n+1][n] = 0; 21 | 22 | /* Основен цикъл */ 23 | for (j = 1; j <= n - 1; j++) { 24 | for (i = 1; i <= n - j; i++) { 25 | m[i][i + j] = INFINITY; 26 | for (k = i; k <= i + j; k++) { 27 | /* Подобряваме текущото решение */ 28 | if ((t = m[i][k - 1] + m[k + 1][i + j]) < m[i][i + j]) { 29 | m[i][i + j] = t; 30 | m[i + j + 1][i] = k; 31 | } 32 | } 33 | for (k = i-1; k < i + j; k++) 34 | m[i][i+j] += f[k]; 35 | } 36 | } 37 | } 38 | 39 | /* Извежда матрицата на минимумите на екрана */ 40 | void PrintMatrix(void) 41 | { unsigned i,j; 42 | printf("\nМатрица на минимумите:"); 43 | for (i = 1; i <= n+1; i++) { 44 | printf("\n"); 45 | for (j = 1; j <= n; j++) 46 | printf("%8lu", m[i][j]); 47 | } 48 | } 49 | 50 | /* Извежда оптималното дърво на екрана */ 51 | void getOrder(unsigned ll, unsigned rr, unsigned h) 52 | { unsigned i; 53 | if (ll > rr) 54 | return; 55 | if (ll == rr) { 56 | for (i = 0; i < h; i++) 57 | printf(" "); 58 | printf("d%u\n", rr); 59 | } 60 | else { 61 | getOrder(ll, m[rr + 1][ll] - 1, h + 1); 62 | for (i = 0; i < h; i++) 63 | printf(" "); 64 | printf("d%lu\n", m[rr + 1][ll]); 65 | getOrder(m[rr + 1][ll] + 1, rr, h + 1); 66 | } 67 | } 68 | 69 | int main(void) { 70 | solve(); 71 | printf("\nМинималната дължина на претегления вътрешен път е: %lu",m[1][n]); 72 | PrintMatrix(); 73 | printf("\nОптимално дърво за претърсване:\n"); getOrder(1,n,0); 74 | return 0; 75 | } -------------------------------------------------------------------------------- /chapter08/triangle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 100 3 | #define MAX2 MAX * (MAX + 1) / 2 4 | #define INFINITY (unsigned)(-1) 5 | 6 | unsigned p[MAX2]; /* Минимална цена за достигане на възел I */ 7 | unsigned pred[MAX2]; /* Предшественик на възел I в мин. път */ 8 | 9 | /* Цени за преминаване през върховете */ 10 | const unsigned v[MAX2] = {0,1,22,33,5,6,77,8,22,7,225,177,738,737,778,39,28,9,10,11,12,13}; 11 | const unsigned n = 6; /* Брой редове в триъгълника */ 12 | 13 | void compare(unsigned ind1, unsigned ind2) 14 | { if (p[ind1] > p[ind2] + v[ind1]) { 15 | p[ind1] = p[ind2] + v[ind1]; 16 | pred[ind1] = ind2; 17 | } 18 | } 19 | 20 | /* Намира минималния път до всеки възел */ 21 | void findMinPath(void) 22 | { unsigned i, j, sum; 23 | /* До първия връх се стига непосредствено */ 24 | for (p[1] = v[1], sum = 0, i = 1; i <= n; i++) { 25 | for (j = 1; j <= i; j++) { 26 | if (j > 1) 27 | compare(sum + j + i - 1, sum + j); 28 | compare(sum + j + i, sum + j); 29 | compare(sum + j + i + 1, sum + j); 30 | } 31 | sum += i; 32 | } 33 | } 34 | 35 | /* Извежда триъгълника на минималните пътища на екрана */ 36 | void print(const unsigned m[]) 37 | { unsigned i, j, sum; 38 | for (sum = 0, i = 1; i <= n; printf("\n"), sum += i++) 39 | for (j = 1; j <= i; j++) 40 | printf("%8u", m[sum + j]); 41 | } 42 | 43 | /* Извежда минималния път до върха x */ 44 | void writePath(unsigned x) 45 | { printf("\n%s%u%s%u", "Пътят до връх номер ", x, " е минимален: ", p[x]); 46 | printf("\nПътят, изведен в обратен ред (индекси): "); 47 | while (x != 1) { 48 | printf("%u ", x); 49 | x = pred[x]; 50 | } 51 | printf("1"); 52 | } 53 | 54 | /* Намира връх от последния ред с минимален път */ 55 | void findMinLastRow(void) 56 | { unsigned i, minInd, end = n * (n + 1) / 2; 57 | for (i = 1 + (minInd = end-n+1); i <= end; i++) 58 | if (p[i] < p[minInd]) 59 | minInd = i; 60 | writePath(minInd); 61 | } 62 | 63 | int main(void) { 64 | unsigned i; 65 | for (i = 0; i < (n + 3)*(n + 2)/2; i++) 66 | p[i] = INFINITY; 67 | printf("Изходен триъгълник:\n"); print(v); 68 | findMinPath(); 69 | printf("\nТриъгълник на минималните пътища:\n"); print(p); 70 | findMinLastRow(); 71 | return 0; 72 | } -------------------------------------------------------------------------------- /chapter09/aselect.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | 5 | const int n = 7; 6 | const int s[MAXN] = { 3, 7, 5, 9, 13, 15, 17 }; 7 | const int f[MAXN] = { 8, 10, 12, 14, 15, 19, 20 }; 8 | 9 | void solve(void) 10 | { int i = 1, j = 1; 11 | printf(" Избрани лекции: %d ", 1); 12 | 13 | while (j++ <= n) 14 | if (s[j - 1] > f[i - 1]) printf("%d ", i = j); 15 | printf("\n"); 16 | } 17 | 18 | int main(void) { 19 | solve(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /chapter09/colorg.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 200 4 | 5 | const int n = 6; 6 | const char A[MAXN][MAXN] = { 7 | { 0, 1, 0, 0, 0, 0 }, 8 | { 1, 0, 1, 0, 0, 1 }, 9 | { 0, 1, 0, 0, 1, 0 }, 10 | { 0, 0, 0, 0, 0, 1 }, 11 | { 0, 0, 1, 0, 0, 0 }, 12 | { 0, 1, 0, 1, 0, 0 } 13 | }; 14 | 15 | int color[MAXN]; 16 | 17 | /* върховете се разглеждат в произволен, а не сортиран по степента им ред */ 18 | void solve1(void) 19 | { int flag, i, j; 20 | for (i = 0; i < n; i++) { /* оцветява i-тия връх с най-малкият възможен цвят */ 21 | int c = 0; 22 | do { 23 | c++; 24 | flag = 1; 25 | for (j = 0; j < n; j++) 26 | if (A[i][j] && color[j] == c) { 27 | flag = 0; 28 | break; 29 | } 30 | } while (!flag); 31 | color[i] = c; 32 | } 33 | } 34 | 35 | void solve2(void) 36 | { int c = 0, cn = 0, i, j; 37 | /* оцветява върхове само с първия цвят, докато е възможно, след това само с 38 | * втория и т.н., докато всички върхове бъдат оцветени 39 | */ 40 | while (cn < n) { 41 | c++; 42 | for (i = 0; i < n; i++) { 43 | if (!color[i]) { 44 | int flag = 1; 45 | for (j = 0; j < n; j++) 46 | if (A[i][j] && color[j] == c) { 47 | flag = 0; 48 | break; 49 | } 50 | 51 | if (flag) { 52 | color[i] = c; 53 | cn++; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | 60 | void showColor(void) 61 | { int i; 62 | for (i = 0; i < n; i++) printf("%d-%d; ", i + 1, color[i]); 63 | printf("\n"); 64 | } 65 | 66 | int main(void) { 67 | int i; 68 | printf("Оцветяване на върховете по алгоритъм 1: \n"); 69 | for (i = 0; i < n; i++) color[i] = 0; 70 | solve1(); 71 | showColor(); 72 | printf("Оцветяване на върховете по алгоритъм 2: \n"); 73 | for (i = 0; i < n; i++) color[i] = 0; 74 | solve2(); 75 | showColor(); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /chapter09/egypt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* намалява p/q, докато p стане равно на 1 */ 4 | void cancel(unsigned long *p, unsigned long *q) { 5 | if (0 == *q % *p) { 6 | *q /= *p; 7 | *p = 1; 8 | } 9 | } 10 | 11 | void solve(unsigned long p, unsigned long q) { 12 | printf("%ld/%ld = ", p, q); 13 | cancel(&p, &q); 14 | 15 | while (p > 1) { 16 | /* намира максималната дроб 1/r, 1/r<=p/q */ 17 | unsigned long r; 18 | r = (q + p) / p; 19 | printf("%d/%ld + ", 1, r); 20 | 21 | /* изчислява p/q - 1/r */ 22 | p = p * r - q; 23 | q = q * r; 24 | cancel(&p, &q); 25 | } 26 | (p > 0) ? printf("%ld/%ld\n", p, q) : printf("\n"); 27 | } 28 | 29 | int main(void) { 30 | solve(3, 7); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /chapter09/fracknap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 1000 4 | 5 | int n = 3; /* брой на предметите */ 6 | float c[MAXN] = { 25, 12, 16 }; /* себестойност на предметите */ 7 | float m[MAXN] = { 10, 8, 8 }; /* количества от предметите */ 8 | float M = 16; /* ограничително тегло на раницата */ 9 | 10 | float ratio[MAXN]; 11 | 12 | void swap(float *a, float *b) 13 | { float s = *a; *a = *b; *b = s; } 14 | 15 | /* сортира предметите по себестойност */ 16 | void sort(void) 17 | { int i, j; 18 | for (i = 0; i < n - 1; i++) 19 | for (j = i + 1; j < n; j++) 20 | if (ratio[j] > ratio[i]) { 21 | swap(&c[i], &c[j]); 22 | swap(&m[i], &m[j]); 23 | swap(&ratio[i], &ratio[j]); 24 | } 25 | } 26 | 27 | /* намира решението */ 28 | void solve(void) 29 | { int i = 0; 30 | float T = 0, V = 0;; 31 | while (T + m[i] <= M) { /* взима цели предмети, докато може */ 32 | printf("Избира 100%% от предмет със стойност %.2f и тегло %.2f \n", c[i], m[i]); 33 | T += m[i]; V += c[i]; 34 | i++; 35 | } 36 | printf("Избира се %.2f%% от предмет със стойност %.2f и тегло %.2f \n", 37 | ((M - T) / m[i]) * 100, c[i], m[i]); 38 | V += (M - T) * (c[i] / m[i]); 39 | printf("Обща получена цена: %.2f\n", V); 40 | } 41 | 42 | int main(void) { 43 | int i; 44 | for (i = 0; i < n; i++) ratio[i] = c[i] / m[i]; 45 | sort(); 46 | solve(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /chapter09/hamgray.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 1000 4 | 5 | /* код на Грей, Хамилтонов цикъл в n-мерен двоичен куб (Хиперкуб) */ 6 | const int n = 3; 7 | int a[MAXN]; 8 | 9 | void print(void) 10 | { int i; 11 | for (i = 1; i <= n; i++) printf("%d ", a[i]); 12 | printf("\n"); 13 | } 14 | 15 | void forwgray(int k); 16 | 17 | /* prototype */ 18 | void backgray(int k) 19 | { if (0 == k) { print(); return; } 20 | a[k] = 1; forwgray(k - 1); 21 | a[k] = 0; backgray(k - 1); 22 | } 23 | 24 | void forwgray(int k) 25 | { if (0 == k) { print(); return; } 26 | a[k] = 0; forwgray(k - 1); 27 | a[k] = 1; backgray(k - 1); 28 | } 29 | 30 | int main(void) { 31 | forwgray(n); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /chapter09/knightg.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 100 4 | #define MAX_MOVES 8 5 | 6 | const unsigned n = 12; 7 | const int moveX[MAX_MOVES] = { +1, -1, +1, -1, +2, +2, -2, -2 }; 8 | const int moveY[MAX_MOVES] = { +2, +2, -2, -2, +1, -1, +1, -1 }; 9 | 10 | int a[MAXN][MAXN], x, y, p; 11 | 12 | int countMoves(int x, int y) 13 | { int i, number = 0; 14 | if (x < 0 || y < 0 || x >= n || y >= n || a[x][y] != 0) 15 | return MAX_MOVES + 1; /* невалиден ход */ 16 | for (i = 0; i < MAX_MOVES; i++) { 17 | int nx = x + moveX[i], ny = y + moveY[i]; 18 | if (nx >= 0 && ny >= 0 && nx < n && ny < n && a[nx][ny] == 0) number++; 19 | } 20 | return number; 21 | } 22 | 23 | void solve(void) { 24 | unsigned i, j, n2; 25 | 26 | /* инициализация */ 27 | for (i = 0; i < n; i++) 28 | for (j = 0; j < n; j++) a[i][j] = 0; 29 | x = 0; 30 | y = 0; 31 | a[0][0] = 1; 32 | p = 1; 33 | 34 | /* повтаря "алчната" стъпка, докато попълни цялата дъска */ 35 | n2 = n * n; 36 | while (p < n2) { 37 | int min = MAX_MOVES + 1, choose; 38 | for (i = 0; i < MAX_MOVES; i++) { 39 | int temp = countMoves(x + moveX[i], y + moveY[i]); 40 | if (temp < min) { 41 | min = temp; 42 | choose = i; 43 | } 44 | } 45 | x += moveX[choose]; 46 | y += moveY[choose]; 47 | a[x][y] = ++p; 48 | } 49 | 50 | /* отпечатва резултата */ 51 | for (i = 0; i < n; i++) { 52 | for (j = 0; j < n; j++) printf("%4d", a[i][j]); 53 | printf("\n"); 54 | } 55 | } 56 | 57 | int main(void) { 58 | solve(); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /chapter09/pi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { long t = 1000000; /* брой тестове */ 7 | double r = 10000; /* радиус на окръжността */ 8 | double r2 = r / 2; 9 | long k = 0, i; 10 | 11 | for (i = 0; i < t; i++) { 12 | long a = random(r) - r2 + 1; 13 | long b = random(r) - r2 + 1; 14 | if (sqrt(a * a + b * b) <= r2) k++; 15 | } 16 | 17 | printf("Приближение на p = %.2f\n", (4.0 * k) / t); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /chapter09/prime_mc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const unsigned n = 127; /* проверява се дали даденото число n е просто */ 5 | const unsigned k = 10; /* брой опити на Монте Карло алгоритъма със случайна база a */ 6 | 7 | /* пресмята a^t mod n; */ 8 | unsigned long bigmod(unsigned long a, unsigned long t, unsigned long n) 9 | { return (t == 1) ? (a % n) : (bigmod(a, t - 1, n) * (a % n)) % n; 10 | } 11 | 12 | char strongRandom(unsigned long n, unsigned long a) 13 | { unsigned long s = 1, t = n - 1, x, i; 14 | 15 | /* частен случай */ 16 | if (n < 2) return 0; 17 | if (n == 2) return 1; 18 | 19 | /* стъпка 1) */ 20 | while (t % 2 != 1) { 21 | s++; 22 | t /= 2; 23 | } 24 | /* стъпка 2) x = a^t mod n; */ 25 | x = bigmod(a, t, n); 26 | if (1 == x) return 1; 27 | /* стъпка 3 */ 28 | for (i = 0; i < s; i++) { 29 | if (x == n - 1) return 1; 30 | x = x * x % n; 31 | } 32 | return 0; 33 | } 34 | 35 | char isPrime(unsigned long n) 36 | { unsigned i; 37 | for (i = 1; i <= k; i++) { 38 | long int a = random(n - 3) + 2; 39 | if (!strongRandom(n, a)) return 0; 40 | } 41 | return 1; 42 | } 43 | 44 | int main(void) { 45 | printf("Числото %d e %s.\n", n, (isPrime(n)) ? "просто" : "съставно"); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /chapter09/schedule.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 1000 4 | 5 | const int n = 5; 6 | const int v[MAXN] = { 50, 40, 30, 20, 15 }; 7 | const int d[MAXN] = { 2, 1, 2, 2, 1 }; 8 | /* оригинална номерация на задачите */ 9 | const int p[MAXN] = { 5, 1, 2, 4, 3 }; 10 | 11 | int index[MAXN], taken[MAXN], tn; 12 | 13 | char feasible(int k) 14 | { int s = 0, i; 15 | for (i = 0; i < n; i++) { 16 | s += index[i]; 17 | if (i == d[k] - 1) s += 1; 18 | if (s > i + 1) return 0; 19 | } 20 | 21 | return 1; 22 | } 23 | 24 | void solve(void) 25 | { int k, i, income; 26 | for (k = 0; k < n; k++) 27 | if (feasible(k)) { 28 | taken[tn++] = k; 29 | index[d[k] - 1]++; 30 | } 31 | 32 | printf("Оптимално разписание: "); 33 | 34 | income = 0; 35 | for (i = 0; i < tn; i++) { 36 | printf("%d ", p[taken[i]]); 37 | income += v[taken[i]]; 38 | } 39 | 40 | printf("\nОбщ доход: %d\n", income); 41 | } 42 | 43 | int main(void) { 44 | int i; 45 | for (i = 0; i < n; i++) index[i] = 0; 46 | tn = 0; 47 | solve(); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /chapter10/entropy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define log2(x) log(x)/log(2) 4 | #define MAX 100 5 | 6 | const double p[MAX] = {0.2, 0.2, 0.15, 0.15, 0.10, 0.10, 0.05, 0.05}; 7 | const unsigned n = 8; /* Брой вероятности */ 8 | 9 | /* Пресмята ентропията на източника */ 10 | double calcEntropy(const double *p, const unsigned n) 11 | { unsigned i; 12 | double sum; 13 | for (sum = i = 0; i < n; i++) 14 | sum -= p[i]*log2(p[i]); 15 | return sum; 16 | } 17 | 18 | /* Пресмята цената на кода */ 19 | double calcValue(const double *p, const unsigned *l, const unsigned n) 20 | { unsigned i; 21 | double sum; 22 | for (sum = i = 0; i < n; i++) 23 | sum += p[i]*l[i]; 24 | return sum; 25 | } 26 | 27 | /* Пресмята дължините на кодовете на отделните букви */ 28 | void calcLengths(unsigned *l, const double *p, const unsigned n) 29 | { unsigned i; 30 | for (i = 0; i < n; i++) 31 | l[i] = (unsigned) ceil(log2(1.0 / p[i])); 32 | } 33 | 34 | int main(void) { 35 | unsigned i; 36 | double entr; 37 | unsigned l[MAX]; 38 | 39 | printf("\n\nИзточник, зададен с честоти на срещане: "); 40 | for (i = 0; i < n; i++) 41 | printf("%2.2lf ",p[i]); 42 | 43 | entr = calcEntropy(p,n); 44 | printf("\nЕнтропия на източника: %8.5lf",entr); 45 | printf("\nТеоретична цена на кода: %8.5lf",entr + 1); 46 | 47 | calcLengths(l,p,n); 48 | printf("\nДължини на кодовете: "); 49 | for (i = 0; i < n; i++) 50 | printf("%u ",l[i]); 51 | 52 | printf("\nЦена на кода при горните дължини: %2.2lf",calcValue(p,l,n)); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /chapter10/lpc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX 100 7 | const char *message = "LLLLLLALABALANICAAAABABABBABABABABAAABABALLLLAABB"; 8 | 9 | void LPCencode(int *code, const char *msg) /* Извършва LPC кодиране на съобщението */ 10 | { double exp; 11 | unsigned n; 12 | if ('\0' == *msg) return; /* Празно входно съобщение */ 13 | for (exp = code[0] = *msg++, n = 1; '\0' != *msg; n++, msg++) { 14 | code[n] = (int) ceil(exp-*msg); 15 | exp = (exp*n + (unsigned char)*msg)/(n+1); 16 | } 17 | } 18 | 19 | void LPCdecode(char *msg, const int *code, const unsigned n) /*Извършва LPC декодиране*/ 20 | { double exp; 21 | unsigned i; 22 | for (exp = *msg++ = *code, i = 1; i < n; i++, msg++) { 23 | *msg = (char)ceil(exp - code[i]); 24 | exp = (exp*i + (unsigned char) *msg) / (i+1); 25 | } 26 | *msg = '\0'; 27 | } 28 | 29 | void print(const int *code, const unsigned n) 30 | { unsigned i; 31 | for (i = 0; i < n; i++) 32 | printf("%4d", code[i]); 33 | } 34 | 35 | int main(void) { 36 | int coded[MAX]; /* Кодирано съобщение */ 37 | char decoded[MAX]; /* Декодирано съобщение */ 38 | 39 | printf("Входно съобщение:\n%s\n", message); 40 | 41 | LPCencode(coded, message); 42 | printf("\nКодирано съобщение:\n"); 43 | print(coded, strlen(message)); 44 | 45 | LPCdecode(decoded, coded, strlen(message)); 46 | printf("\nДекодирано съобщение:\n%s", decoded); 47 | return 0; 48 | } --------------------------------------------------------------------------------