算法學習(一):遞歸與分治策略(2)

幾個經典題目

1.二分搜索:給定已排好序的n個元素a[0:n-1],現要在這n個元素中找出一指定元素x。

比較簡單,直接貼代碼

int binary_search(int a[],int x)//二分搜索,找到x返回角標,不存在則返回-1;
{
   int low=0,high=n-1;
   while(low<=high)
   {
       int mid=(low+high)/2;
       if(a[mid]==x)
        return mid;
       else if(a[mid]>x)
        high=mid-1;//左搜索
       else
        low=mid+1;//右搜索
   }
   return -1;
}

2歸併排序

對於兩個有序數組,可通過一重循環,將其排序。將數組逐次分割,最後分割n個數組,可以認爲此數組有序。然後在往回歸併,最終得到有序數列。

完整代碼如下:

#include <iostream>

using namespace std;
void merge_div(int low,int high);//分割,歸併
void merge_sort(int low,int high,int mid);//排序
int a[10]={3,16,2,19,75,38,76,1};
void input();
int main()
{
    merge_div(0,7);
    input();
    return 0;
}
void merge_div(int low,int high)
{
    if(low>=high)
        return ;
    int mid=(low+high)/2;
    merge_div(low,mid);
    merge_div(mid+1,high);
    merge_sort(low,high,mid);
}
void merge_sort(int low,int high,int mid)
{
    int i=low,m=mid;
    int j=mid+1,n=high;
    int k=0;
    int t[20];
    while(i<=m&&j<=n)//對兩個有序數組進行排序,並存到臨時數組中
    {
        if(a[i]<a[j])
            t[k++]=a[i++];
        else
            t[k++]=a[j++];
    }
    while(i<=m)
        t[k++]=a[i++];
    while(j<=n)
        t[k++]=a[j++];
    k=0;
    for(int i=low;i<=high;i++)//將臨時數組中的有序數列複製到原數組中
        a[i]=t[k++];
}
void input()
{
    for(int i=0;i<7;i++)
        cout<<a[i]<<" ";
    cout<<a[7]<<endl;
    return ;
}

3.快速排序

所謂快速排序,就是用最快的速度,將數組排好序。對於數組a[p:r]其基本思想及步驟是:

①:分解:以a[p]爲基準元素將a[p:r]劃分成3段a[p:q-1],a[q]和a[q+1:r],使得a[p:q-1]中任何元素小於等於a[q],a[q+1,r]中任何元素大於等於a[q]。下標q在劃分過程中確定。

②:排序:遞歸調用快速排序算法,分別對分好的區間排序

③:合併:在找點的過程中,以排好序,所以合併後已然排好序。

完整代碼如下:

#include <iostream>
/*
    快速排序算法
*/
using namespace std;
int n;
int a[100];
void readdata();
void quicksort(int low,int high);
int position(int low,int high);
void input();
int main()
{
    readdata();//讀入數據
    quicksort(0,n-1);//調用快速排序算法
    input();//輸出已排好序的數列
    return 0;
}
void readdata()
{
    cin>>n;
    for(int i=0; i<n; i++)
        cin>>a[i];
}
void quicksort(int low,int high)
{
    int pos;
    if(low<=high)
    {
        pos=position(low,high);//此點將數組分爲兩組,左邊都比此點數據小,右邊都比此點數據大
        quicksort(low,pos-1);//對左邊調用快排
        quicksort(pos+1,high);//對右邊調用快排
    }
    return ;
}
int position(int low,int high)
{
    int num=a[low];
    int i=low,j=high;
    while(i<j)
    {
        while(i<j&&a[j]>num)//從右向左找比num小的點。注意i<j是必要條件,否則會出bug
            j--;
        if(i<j)//將此點賦值給當前目標點位置
        {
            a[i]=a[j];
            i++;
        }
        while(i<j&&a[i]<num)//從左向右找比num大的點。注意i<j是必要條件,否則會出bug
            i++;
        if(i<j)//將此點賦值給當前目標點位置
        {
            a[j]=a[i];
            j--;
        }

    }
    a[i]=num;//將num賦值給找到的位置
    return i;//返回位置點
}
void input()
{
    for(int i=0;i<n-1;i++)
        cout<<a[i]<<" ";
    cout<<a[n-1]<<endl;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章