算法设计与分析

来源:互联网 发布:程序员mac 编辑:程序博客网 时间:2024/05/16 09:13

算法与程序

一、满足四条性质

  1. 输入
  2. 输出
  3. 确定性
  4. 有穷性

二、NP完全性理论问题

NP类问题是非确定性计算模型下的易验证问题类。

所有可以在多项式时间内求解的判定问题构成P类问题


三、递归的部分算法设计与分析

1、二分搜索技术

二分搜索算法的基本思路是对给定已排好序的n个元素a[0:n-1]在这n个元素中找出一个特定元素x。
运用分治的思想,将n个元素以n/2为中心对半分。if(x==a[n/2])如果成立则n/2的位置就是x元素在a[]中的位置。x<a[n/2]则在左边,反之x在n/2的右边.

//二分搜索,需要数字a[]先从低到高排序        static int BinarySearch(int a[],int x,int n){        int left=0;        int right=n-1;        while(left<=right){            int middle=(left+right)/2;            if(x==a[middle]) return middle;            if(x>a[middle])left=middle+1;            else right=middle-1;        }        return -1;    }

2、合并排序算法

合并算法的基本思想是将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成要求的排好序的集合。
基本算法描述如下:

void MergeSort(Type a[],int left,int right) {        if(left<right){                int i=(left+right)/2;                MergeSort(a,left,i);                MergeSort(a,i+1,right);                Merge(a,b,left,i,right);                Copy(a,b,left,right);        }}

中Merge()是将a[left:i]与a[i+1:right]中的元素从小到大排序到b[]中
Copy是将b[left:right]复制到a[left:right]

//归并排序    static void MergeSort(int a[],int left,int right){        if(left<right){            int i=(left+right)/2;            MergeSort(a,left,i);            MergeSort(a,i+1,right);            //Merge(a[],b[],left,i,right)            int m=left;            int n=i+1;            int k=left;//left-right            int b[]=new int[10000];            //判断a[left->i]~a[m]             //    a[i+1->right]~a[n]            while(m<=i&&n<=right){                if(a[m]>a[n]){                    b[k++]=a[n++];                }                else {                    b[k++]=a[m++];                }            }            if(m>i){                while(n<=right){                    b[k++]=a[n++];                }            }            else if(n>right){                while(m<=i){                    b[k++]=a[m++];                }            }            //把b[]复制给a[]            for(int j=left;j<=right;j++)                a[j]=b[j];        }    }

3、快速排序

快速排序算法的思想是对于输入的子数组a[p:r]按以下三个步骤进行排序:
1. 分解
2. 递归求解
3. 合并
基于这个思想算法思路为:

void QuickSort(Type a[],int p,int r){    if(p<r){        int q=Partition(a,p,r);        QuickSort(a,p,q-1);        QuickSort(a,q+1,r);    }}

其中Partition()是对于a[p:r]
取x=a[p]对于a[p:r]分成一个位置j,a[j]=x,a[p:j-1]是小于a[j] (即x),a[j+1:r]是大于a[j].
算法思路如下:

    int Partition(Type a[],int p,int r){    int i=p,j=r+1;    int x=a[p];    while(true){            while([++i]<x&&i<r);            while([--j]>x);            if(i>=j)break;            Swap(a[i],a[j]);        }        a[p]=a[j];        a[j]=x;        return j;    }

我是将Partition()融入在QuickSort()中,代码如下:

//快速排序    static void QuickSort(int a[],int p,int r){        if(p<r){            int i=p,j=r+1;            int x=a[p];            while(true){                while(a[++i]<x&&i<r);                while(a[--j]>x);                if(i>=j){                    break;                }                else{                    int temp=a[i];                    a[i]=a[j];                    a[j]=temp;                }            }            a[p]=a[j];            a[j]=x;            QuickSort(a,p,j-1);            QuickSort(a,j+1,r);        }    }

4、线性时间选择

该算法是模仿快速排序算法设计出来的。实际是对数组a[p:r]进行划分,分成a[p:i-1]和a[i+1:r].其中a[p:i-1]的元素全部小于a[i],a[i+1:r]的元素全部大于a[i];如果x>i则,查找的位置在i的右边,反之在i的左边。直到p等于r确定了要查找位置的元素值就是a[p].

static int RandomizedSelect(int a[],int p,int r,int k){        if(p==r) return a[p];        //i取p 将p:r排序,分成a[p:i-1]和a[i+1:r]        int i=p,j=r+1;        int x=a[p];        while(true){            while(a[++i]<x&&i<r);            while(a[--j]>x);            if(i>=j){                break;            }            else{                int temp=a[i];                a[i]=a[j];                a[j]=temp;            }        }        a[p]=a[j];        a[j]=x;//p-j 小于j+1-r        if(k<=(j-p+1)){            return RandomizedSelect(a,p,j,k);        }        else{           return RandomizedSelect(a,j+1,r,k+p-(j+1));          }    }}