• 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;
    }

      上面的程序还可以优化。

      先到这里,有空再继续。

  • 相关阅读:
    一个简单的爬虫case2
    一个简单的爬虫case1
    Kick Start 2018-Round H-Problem C. Let Me Count The Ways
    Kick Start 2018-Round H-Problem B. Mural
    Kick Start 2018-Round H-Problem A. Big Buttons
    211. Add and Search Word
    HDU-1506 Largest Rectangle in a Histogram
    HDU-1236 排名
    HDU-1009 FatMouse' Trade
    HDU-1231 最大连续子序列
  • 原文地址:https://www.cnblogs.com/Frandy/p/algorithm_course_1_2.html
Copyright © 2020-2023  润新知