Algorithm Design and Analysis
Chapter 1-----Basic Concepts in Algorithmic Analysis
1)Binary Search
- Problem Description
Let A[1…n] be a sequence of n elements. Consider the problem of determining whether a given element x is in A. - Input
- An array A[1…n] of n elements sorted in nondecreasing order;
- x;
- Output
j if x=A[j], and 0 otherwise; - Pseudo code
1. low←1; high←n; j←0; 2. while (low<=high) and (j=0) 3. mid←⌊low+high)/2⌋; 4. if x=A[mid] then j←mid; 5. else if x<A[mid] then high←mid–1; 6. else low←mid+1; 7. end while; 8. return j;
- Complexity
Max: ⌊log n⌋+1
Min: 1
Average: log n - C++ code
#include <iostream> using namespace std; //二分查找,返回元素所在位置 int Binary_Search(int A[],int len,int x){ int low = 0,high = len; while(low <= high){ int mid = (low+high)/2; if(x == A[mid]){ return (mid+1); } else if(x > A[mid]){ low = mid+1; } else{ high = mid-1; } } } int main(){ int A[] = {1,4,5,7,8,9,10,12,15,22,23,27,32,35}; cout<<Binary_Search(A,14,22)<<endl; return 0; }
2)Merging Two Sorted Lists
- Problem Description
Suppose we have an array A[1…m] and three indices p, q, and r, with 1 <= p <= q < r <= m,
such that both the subarrays A[p…q] and A[q+1…r] are individually sorted in nondecreasing order.
We want to rearrange the elements in A so that the elements in the subarray A[p…r] are sorted in nondecreasing order. - Input
- A[1…m];
- p, q, and r, and 1 <= p <= q < r <= m, such that both A[p…q] and A[q+1…r] are sorted individually in nondecreasing order;
- Output
A[p…r] contains the result of merging the two subarrays A[p…q] and A[q+1…r]; - Pseudo code
1. s←p; t←q+1; k←p; 2. while s<=q and t<=r 3. if A[s]<=A[t] then 4. B[k]←A[s]; 5. s←s+1; 6. else 7. B[k]←A[t]; 8. t←t+1; 9. end if; 10. k←k+1; 11. end while; 12. if s=q+1 then B[k…r]←A[t…r] 13. else B[k…r]←A[s…q] 14. end if 15. A[p…r]←B[p…r]
- Number of Comparisons
Max : n-1 (n=n1+n2)
Min : n1
Average : ⌊n/2⌋ ~ n-1 - Number of Assignments
2n - C++ code
#include <iostream> using namespace std; //归并两个有序数组 int *Merge_Lists(int *list_A,int A_len,int *list_B,int B_len,int *list_merged){ int A_s = 0,B_t = 0; int k; for(k = 0;A_s<A_len && B_t<B_len;k++){ if(list_A[A_s] <= list_B[B_t]){ list_merged[k] = list_A[A_s]; A_s++; } else{ list_merged[k] = list_B[B_t]; B_t++; } } if(A_s == A_len) for(;B_t<B_len;B_t++,k++) list_merged[k] = list_B[B_t]; else for(;A_s<A_len;A_s++,k++) list_merged[k] = list_A[A_s]; return list_merged; } int main(){ int A[5] = {1,4,6,8,9},B[8] = {2,5,7,12,45,46,49,61}; int mergedList[13]; Merge_Lists(A,5,B,8,mergedList); for(int i = 0;i<13;i++) cout<<*(mergedList+i)<<" "; return 0; }
3)Selection Sort
-
Problem Description
Let A[1…n] be an array of n elements.
First, we find the minimum element and store it in A[1].
Next, we find the minimum of the remaining n-1 elements and store it in A[2].
We continue this way until the second largest element is stored in A[n-1]. -
Input
A[1…n]; -
Output
A[1…n] sorted in non-decreasing order; -
Pseudo code
3. for i←1 to n-1 4. k←i; 5. for j←i+1 to n 6. if A[j]<A[k] then k←j; 7. end for; 8. if k≠i then interchange A[i] and A[k]; 9. end for;
-
Number of Comparisons
n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1) -
Number of Assignments
Max: 3(n-1)
Min: 0 -
C++ code
#include <iostream> using namespace std; void Selection_Sort(int *A,int A_len){ int min_pos; for(int i = 0;i<A_len-1;i++){ min_pos = i; for(int j = i+1;j<A_len;j++){ if(*(A+j)<*(A+min_pos)){ min_pos = j; } } if(min_pos != i){ int temp = *(A+i); *(A+i) = *(A+min_pos); *(A+min_pos) = temp; } } } int main(){ //Selection Sort int A[10] = {3,9,7,569,58,642,3,5,8,65}; for(int i = 0;i<10;i++) cout<<*(A+i)<<" "; cout<<endl; Selection_Sort(A,10); for(int i = 0;i<10;i++) cout<<*(A+i)<<" "; cout<<endl; return 0; }
4)Insertion Sort
- Problem Description
We begin with the subarray of size 1, A[1], which is already sorted.
Next, A[2] is inserted before or after A[1] depending on whether it is smaller than A[1] or not.
Continuing this way, in the i th iteration, A[i] is inserted in its proper position in the sorted subarray A[1 … i-1].
This is done by scanning the elements from index i-1 down to 1, each time comparing A[i] with the element at the current position.
In each iteration of the scan, an element is shifted one position up to a higher index.
This process of scanning, performing the comparison and shifting continues until an element less than or equal to A[i] is found, or when all the sorted sequence so far is exhausted.
At this point, A[i] is inserted in its proper position, and the process of inserting element A[i] in its proper place is complete. - Input
A[1…n]; - Output
A[1…n] sorted in non-decreasing order; - Pseudo code
1. for i←2 to n 2. x←A[i]; 3. j←i-1; 4. while (j>0) and (A[j]>x) 5. A[j+1]←A[j]; 6. j←j-1; 7. end while; 8. A[j+1]←x; 9. end for;
- Number of Comparisons
Max: n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1)
Min: n-1 - Number of Assignments
Max: n ( n − 1 ) 2 + 2 ( n − 1 ) \frac{n(n-1)}{2}+2(n-1) 2n(n−1)+2(n−1)
Min: (n-1)+(n-1)
Others: Number of Comparisons+(n-1) - C++ code
#include <iostream> using namespace std; //插入排序 void Insertion_Sort(int *A,int A_len){ for(int i = 1;i<A_len;i++){ int x = A[i]; int j = i-1; while(j>=0 && A[j]>x){ A[j+1] = A[j]; j--; } A[j+1] = x; } } int main(){ int A[10] = {3,9,7,569,58,642,3,5,8,65}; for(int i = 0;i<10;i++) cout<<*(A+i)<<" "; cout<<endl; Insertion_Sort(A,10); for(int i = 0;i<10;i++) cout<<*(A+i)<<" "; cout<<endl; return 0; }
5)Bottom-Up Merge Sorting
- Question Description
Let A be an array of n elements that is to be sorted.
We first merge ⌊n/2⌋ consecutive pairs of elements to yield ⌊n/2⌋ sorted sequences of size 2.
If there is one remaining element, then it is passed to the next iteration.
Next, we merge ⌊n/4⌋ pairs of consecutive 2-element sequences to yield ⌊n/4⌋ sorted sequences of size 4.
If there are one or two remaining elements, then they are passed to the next iteration.
If there are three elements left, then two (sorted) elements are merged with one element to form a 3-element sorted sequence.
Continuing this way, in the jth iteration, we merge ⌊n/2j⌋ pairs of sorted sequences of size 2j-1 to yield ⌊n/2j⌋ sorted sequences of size 2j.
If there are k remaining elements, where 1<=k<=2j-1, then they are passed to the next iteration.
If there are k remaining elements, where 2j-1<k<2j, then these are merged to form a sorted sequence of size k. - Input
An array A[1…n] of n elements; - Output
A[1…n] sorted in nondecreasing order; - Pseudo code
1. t←1; 2. while t<n 3. s←t; t←2s; i←0; 4. while i+t≤n 5. MERGE(A, i+1, i+s, i+t); 6. i←i+t; 7. end while; 8. if i+s<n then MERGE(A, i+1, i+s, n); 9. end while;
- Number of Comparisons
Max: n logn - n + 1
Min: (n log n)/2 - Number of Assignments
2n logn - C++ code
#include <iostream> using namespace std; //归并排序 void MERGE(int *A,int p,int q,int r){ p--;q--;r--; int B[r-p+1]; int s = p; int t = q+1; int k = 0; while(s<=q && t<= r){ if(A[s]<=A[t]){ B[k] = A[s]; s++; } else{ B[k] = A[t]; t++; } k++; } if(s == q+1){ for(;t<=r;t++,k++) B[k] = A[t]; } else{ for(;s<=q;s++,k++) B[k] = A[s]; } for(int i = 0;i<k && p<=r;i++,p++){ A[p] = B[i]; } } void Bottom_Up_Merge_Sort(int *A,int A_len){ int merge_size = 1,array_size,i; while(merge_size<A_len){ array_size = merge_size; merge_size = 2*array_size; for(i = 0;i+merge_size<=A_len;i += merge_size){ MERGE(A,i+1,i+array_size,i+merge_size); } if(i+array_size < A_len) MERGE(A,i+1,i+array_size,A_len); } } int main(){ int A[10] = {3,9,7,569,58,642,3,5,8,65}; for(int i = 0;i<10;i++) cout<<*(A+i)<<" "; cout<<endl; Bottom_Up_Merge_Sort(A,10); for(int i = 0;i<10;i++) cout<<*(A+i)<<" "; cout<<endl; return 0; }