Algorithm Course Review(1.2)
几种经典的查找和排序算法。
查找算法有线性查找,二分查找。线性查找就是遍历所有元素,直到找到目标元素,时间复杂度为O(n),相对于输入规模是线性的。二分查找,在数组已经排序的情况下,可以进行二分查找,每次缩小一半的查找范围,时间复杂度为O(logn)。需要注意的是,算法里面的log表示log2.
这两个算法的代码如下:
#include <vector> #include <iostream> using namespace std; /* * 线性查找,即遍历所有元素查找 */ template<class Type> int LinearSearch(vector<Type>& A, Type x) { int j = -1; for(unsigned int i=0;i<A.size();i++) { if(x==A[i]) { j = i; break; } } return j; } /* * 二分查找,即对半查找,要求数组已排序 */ template<class Type> int BinarySearch(vector<Type>& A, Type x) { int low = 0; int high = A.size()-1; int j = -1; while(low<=high && j==-1) { int mid = (low+high)/2; if(x==A[mid]) j = mid; else if(x<A[mid]) high = mid-1; else low = mid+1; } return j; }
再看排序算法,主要有选择排序,插入排序,归并排序和快速排序。
选择排序,就是处理第i个元素时,从剩余的元素里面选出最小的,与i位置元素交换,那么就是把第i小的元素放在第i个位置,即选择过程。比较次数n(n-1)/2.
插入排序,从第二个元素开始,处理第i个元素时,从前面的元素里找出比第i个元素小的位置j,那么x就应该排在j的后面,也即插入过程。比较次数也是n(n-1)/2.
快速排序,通过一次快速排序,将数组的元素分为独立的两部分,其中一部分的所有元素比另一部分小。然后对这两部分再进行快速排序,递归实现。
归并排序,通过归并步骤,将两个有序数组合并为一个有序数组。归并排序,就是将数组不断划分为小的数组,数组长度为1时,即为一个有序数组,然后逐级归并,实现排序。
代码如下:
#include <vector> #include <iostream> using namespace std; /* * 每次从剩余的元素里面找出最小的, * 放在第i个位置,那么就是第i个位置放的元素是第i小的, * 即选择过程 */ template<class Type> void SelectSort(vector<Type>& A) { int i=0,j=0,k=0; int n=A.size(); for(i=0;i<n-1;i++) { k = i; for(j=i+1;j<n;j++) { if(A[j]<A[k]) k = j; } if(k!=i) { Type t = A[k]; A[k] = A[i]; A[i] = t; } } } /* 每次在前面找到x的合适位置, * A[j]<x时,把x放在A[j+1]上 * 即插入过程 */ template<class Type> void InsertSort(vector<Type>& A) { int i=0,j=0; int n = A.size(); for(i=1;i<n;i++) { Type x=A[i]; j=i-1; while(j>=0 && A[j]>x) { A[j+1]=A[j]; j=j-1; } A[j+1]=x; } } /* * 通过一趟快速排序将数据分割成独立的两部分, * 其中一部分比另外一部分的所有数据都要小, * 然后再对这两部分数据分别进行快速排序 * ref: http://blog.csdn.net/shiwenbin333/article/details/4528516 */ template<class Type> void quicksort(vector<Type>& A,int left,int right) { Type temp = A[left]; int i=left+1; int j=right; int cur=left; bool direction = false; while(i<=j) { if(direction) { if(A[i]>temp) { A[cur] = A[i]; cur = i; direction = false; } i++; } else { if(A[j]<temp) { A[cur] = A[j]; cur = j; direction = true; } j--; } } A[cur] = temp; if(cur-left>1) quicksort(A,left,cur-1); if(right-cur>1) quicksort(A,cur+1,right); } template<class Type> void QuickSort(vector<Type>& A) { quicksort(A,0,A.size()-1); } /* * 归并步骤,将两个有序数组合并为一个有序数组 */ template<class Type> void mergearray(vector<Type>& A,int p,int q,int r) { vector<Type> B(r-p+1); int s=p,t=q+1,k=0; while(s<=q && t<=r) { if(A[s]<=A[t]) { B[k] = A[s]; s = s + 1; } else { B[k] = A[t]; t = t + 1; } k = k + 1; } while(s<=q) B[k++]=A[s++]; while(t<=r) B[k++]=A[t++]; for(s=0;s<k;s++) A[p+s]=B[s]; } /* * 归并排序,将数组不断划分,然后逐级归并,实现排序 * ref: http://blog.csdn.net/morewindows/article/details/6678165 */ template<class Type> void mergesort(vector<Type>& A,int p,int r) { if(p<r) { int mid = (p+r)/2; mergesort(A,p,mid); mergesort(A,mid+1,r); mergearray(A,p,mid,r); } } template<class Type> void MergeSort(vector<Type>& A) { mergesort(A,0,A.size()-1); } template<class Type> void print(vector<Type>& A) { for(unsigned int i=0;i<A.size();i++) cout << "\t" << A[i]; cout << endl; } int main() { int b[] = {9,3,2,6,4,5,8,7}; vector<int> A(b,b+8); print(A); // SelectSort(A); // InsertSort(A); // QuickSort(A); MergeSort(A); print(A); return 0; }
上面的程序还可以优化。
先到这里,有空再继续。