Chapter 2-Introduction to Algorithms
Summary: This chapter describes the examples of insertion sorting and algorithm analysis, proof of non-variant loops, combined sorting (divide and conquer), and algorithm analysis.
1. Insert sorting
Similar to the playing card insertion process, set a [1... j-1] is an array of sorted order, insert a [J] into a [1... in J-1], making a [J] an array of sorted orders, j <-2 to length [A]
Algorithm Analysis: In the best case, the entire array is already ordered, O (N)
In the worst case, the entire array is in reverse order, O (N ^ 2)
Average, O (N ^ 2)
Is a stable sorting
Algorithm Optimization: Insert a [J] into a [1... j-1], you can use the binary search method, which can change the efficiency of finding the appropriate location, but still need to move the elements of the array one by one.
Pseudocode
Insertion-sort () <br/> for j <-2 to length [a] <br/> DO <br/> key <-A [J] <br/> I <-J-1 <br /> while I> 0 and a [I]> key <br/> DO <br/> A [I + 1] <-A [I] <br/> I <-i-1 <br/> A [I + 1] <-key <br/>
C ++ code
# Include <iostream> <br/> using namespace STD; </P> <p> void insertsort (int A [], int length) // ° ''' limit μ ½ ''' limit <br/> {<br/> for (Int J = 1; j <length; j ++) <br/>{< br/> int key = A [J]; <br/> int I = J-1; <br/> while (I> = 0 & A [I]> key) <br/> {<br/> A [I + 1] = A [I]; <br/> I --; <br/>}< br/> A [I + 1] = key; <br/>}</P> <p> int main () <br/>{< br/> int A [7] = {3, 4,, 9 }; <br/> int length = sizeof (a)/sizeof (INT); <br/> insertsort (A, length ); <br/> for (INT I = 0; I <length; I ++) <br/>{< br/> cout <A [I] <""; <br/>}< br/> cout <Endl; <br/> return 0; <br/>}
2. Non-changing cycle
Three types of proof: initialization, persistence, and Termination
3. Merge and sort
Divide and conquer: divide the original problem into N subproblems with a small scale and similar structure to the original problem. Solve these subproblems recursively and then merge the results, the problem is solved.
Algorithm Analysis: time complexity O (nlgn)
Space complexity O (N)
Stable sorting
C ++ code
Void Merge (int A [], int P, int Q, int R) // merge sorted a [p... q-1] And a [Q... r-1], sorted from small to large <br/>{< br/> int n1 = Q-P; <br/> int n2 = r-Q; <br/> int * Left = new int [N1]; <br/> int * Right = new int [n2]; <br/> int I; <br/> for (I = 0; I <N1; I ++) <br/> left [I] = A [p + I]; <br/> for (I = 0; I <N2; I ++) <br/> right [I] = A [q + I]; <br/> I = 0; <br/> Int J = 0; <br/> int K = P; <br/> while (I <N1 & J <N2) <br/> {<br/> If (left [I] <right [J]) <br/> A [k ++] = left [I ++]; <br/> else <br/> A [k ++] = right [J ++]; <br/>}< br/> If (j <N2) <br/>{< br/> while (j <N2) <br/> A [k ++] = right [J ++]; <br/>}< br/> if (I <N1) <br/>{< br/> while (I <N1) <br/> A [k ++] = left [I ++]; <br/>}</P> <p> void mergesort (int A [], int begin, int end) // sort from a [begin] to a [end-1] <br/>{< br/> If (begin> = end-1) <br/> return; <br/> int r = (begin + end)/2; <br/> mergesort (A, begin, R); <br/> mergesort (A, R, end); <br/> Merge (A, begin, R, end); <br/>}</P> <p> int main () <br/> {<br/> int A [7] = {3, 4, 2, 1, 8, 0, 9}; <br/> int length = sizeof () /sizeof (INT); <br/> // insertsort (A, length); <br/> mergesort (A, 0, length ); <br/> for (INT I = 0; I <length; I ++) <br/>{< br/> cout <A [I] <""; <br/>}< br/> cout <Endl; <br/> while (1); <br/> return 0; <br/>}
Exercise questions]
1. Select sort
Find the smallest element in a, swap it with a [0], find the minimum element in a, swap it with a [1], and so on ..
Algorithm Analysis: time complexity O (N ^ 2)
Stable sorting
Pseudocode:
Selection-sort () <br/> for I <-1 to length [a]-1 <br/> do smallest <-I <br/> for j <-I + 1 to length [] <br/> do if a [J] <A [smallest] <br/> then smallest <-j <br/> exchange a [I] <-> A [smallest] <br/>
Q: Why does the I loop reach length [a]-1? Because the first n-1 must be the smallest n-1 element, then the nth element must be the largest element, so the last loop can be saved.
C ++ code:
Void selectionsort (int A [], int length) <br/>{< br/> for (INT I = 0; I <length-1; I ++) <br/>{< br/> int smallest = I; <br/> for (Int J = I + 1; j <length; j ++) <br/> if (a [smallest]> A [J]) <br/> smallest = J; <br/> int temp = A [I]; <br/> A [I] = A [smallest]; <br/> A [smallest] = temp; <br/>}</P> <p> int main () <br/>{< br/> int A [7] = {3, 4,, 9 }; <br/> int length = sizeof (a)/sizeof (INT); <br/> selectionsort (A, length ); <br/> for (INT I = 0; I <length; I ++) <br/>{< br/> cout <A [I] <""; <br/>}< br/> cout <Endl; <br/> while (1); <br/> return 0; <br/>}
2. Binary Search (time complexity O (lgn ))
1) Non-recursion (iteration)
// Binary search (iteration) <br/> int iterativebinarysearch (int A [], int V, int low, int high) <br/>{< br/> while (low <= high) <br/>{< br/> int mid = (low + high)/2; <br/> if (a [Mid] = V) <br/> return mid; <br/> else if (V> A [Mid]) <br/> low = Mid + 1; <br/> else <br/> high = mid-1; <br/>}< br/> return NULL; <br/>}
2) Recursion
Int recursivebinarysearch (int A [], int V, int low, int high) <br/>{< br/> If (low> high) <br/> return-1; <br/> int mid = (low + high)/2; <br/> If (V = A [Mid]) <br/> return mid; <br/> else if (V> A [Mid]) <br/> return recursivebinarysearch (A, V, Mid + 1, high ); <br/> else return recursivebinarysearch (A, V, low, mid-1); <br/>}
3. please give an algorithm with the running time of O (nlgn) so that it can be given when a set S consisting of n integers and another integer x is given, determine whether there are two elements in s whose sum is equal to or equal to X.
Algorithm ideas:
Train of Thought 1: Sort S (O (nlgn), remove the repeated elements (O (N) in S, calculate z = x-y for each element in S, integrate all Z aggregation into s' (O (n), sort the s' (O (nlgn), and merge S and s '. If two consecutive equal elements exist in the merged set, the two elements in S are equal to or equal to X.
Void removethesame (int A [], Int & length) <br/>{< br/> for (INT I = 1; I <length; I ++) <br/> {<br/> if (a [I] = A [I-1]) <br/> {<br/> Int J = I; <br/> while (j <length) <br/> {<br/> A [J] = A [J + 1]; <br/> J ++; <br/>}< br/> length --; <br/>}</P> <p> bool findsumx1 (int A [], int X, int length) <br/>{< br/> mergesort (A, 0, length); <br/> removethesame (A, length ); <br/> int * B = new int [length]; <br/> for (INT I = 0; I <length; I ++) <br/> B [I] = x-A [I]; <br/> mergesort (B, 0, length); <br/> int Len = Length + length; <br/> int * c = new int [Len]; <br/> for (INT I = 0; I <length; I ++) <br/> C [I] = A [I]; <br/> for (INT I = length; I <Len; I ++) <br/> C [I] = B [I-length]; <br/> Merge (C, 0, length, Len ); <br/> for (INT I = 1; I <Len; I ++) <br/>{< br/> If (C [I] = C [I-1]) <br/> return true; <br/>}< br/> return false; <br/>}
Train of Thought 2: Sort S (O (nlgn), calculate z = x-y for element y in S, and search for Z (O (lgn) from second points in S )), if it is found, it indicates that it exists. A maximum of N cycles, complexity O (nlgn)
Bool findsumx2 (int A [], int X, int length) <br/>{< br/> mergesort (A, 0, length); <br/> removethesame (, length); <br/> for (INT I = 0; I <length; I ++) <br/>{< br/> int z = x-A [I]; <br/> If (recursivebinarysearch (A, Z, 0, length )! =-1) <br/> return true; <br/>}< br/> return false; <br/>}
[Questions]
1. Use the complexity of O (nlgn) to calculate the number of Reverse Order pairs in any arrangement of the given n elements (Tip: Modify the merge order)
Int merge2 (int A [], int P, int Q, int R) // A [p... q-1] And a [Q... r-1] <br/> {<br/> int n1 = Q-P; <br/> int n2 = r-Q; <br/> int * Left = new int [N1]; <br/> int * Right = new int [n2]; <br/> int I; <br/> for (I = 0; I <N1; I ++) <br/> left [I] = A [p + I]; <br/> for (I = 0; I <N2; I ++) <br/> right [I] = A [q + I]; <br/> I = 0; <br/> Int J = 0, K = P; <br/> int CNT = 0; <br/> while (I <N1 & J <N2) <br/> {<br/> If (right [J] <left [I]) <br/> {<br/> A [k ++] = right [J ++]; <br/> CNT + = n1-i; <br/>}< br/> else <br/> A [k ++] = left [I ++]; <br/>}< br/> if (I <N1) <br/> while (I <N1) <br/> A [k ++] = left [I ++]; <br/> If (j <N2) <br/> while (j <N2) <br/> A [k ++] = right [J ++]; <br/> return CNT; <br/>}</P> <p> int findinversion (int A [], int low, int high) <br/>{< br/> If (low> = high-1) <br/> return 0; <br/> int r = (low + high)/2; <br/> int COUNT = 0; <br/> count + = findinversion (A, low, R); <br/> count + = findinversion (A, R, high); <br/> count + = merge2 (A, low, R, high); <br/> return count; <br/>}< br/>