首选算法的定义是:解决问题的方法和过程。它是程序的灵魂。

算法的分类:一类叫数值算法;另一类是非数值算法。

算法的表示形式:

1用自然语言描述

2.用流程图表示

3.用NS流程图表示

4.用伪代码表示

算法的性能评估:

算法的优劣的指标通常称为算法的复杂度。

算法的复杂度又分为:时间复杂度和空间复杂度。-----更深层次的算法问题可以参看《算法分析》这本书。

算法的一般思想

1.穷举法思想  

穷举法(exhausitve attack method)称强力发(brute-force method),是一种最直接,最简单的方法,同时又是最耗时的算法思想。

基本思想:在可能的解空间中穷举出每一种可能的解,并对没一个可能的解进行判断,从中知道答案。

实际操作:最关键的步骤是划定问题的解空间。注意的是:1是解空间的划定必须保证覆盖问题的全部解,2解空间集合及文艺的解集一定是离散的集合,就是所集合中的原始是可列的、有限的。

优缺点:优点是确保得到问题的全部解。缺点是运算效率十分低下。

2.递归和分治思想

递归和分治思想往往是相伴而生的,

在解决一些规模大的问题时,常常将问题分解,具体来说就是将一个规模大的问题分割成规模较小的同类问题,然后将这些较小的问题逐个解决,最终将整个大问题解决。这种分而治之的思想称为分治思想。

递归思想就是一种直接或者间接的用原算法本身的一种算法。

递归算法必须注意以下几点:1.每个递归函数都必须有一个非递归的定义的初始值,作为递归的结束标志。2在设计递归算法时,要解决的问题需要具有递归性。3虽然采用递归算法解决问题更加方便和但是递归发的运行较低,时间和空间复杂度都比较高。

在实际算法设计中,递归和分治如同一对兄弟,经常结合在一起用。

3.贪心算法

所谓的贪心算法就是总是做出当前看来最好的选择的算法。

要是贪心算法求解问题,问题应当具备以下性质:

1.贪心选择性质:所谓贪心选择性质就是指所求解的问题的整体最优解可以通过局部最优得到。所谓局部最优就是指当前的状态下做出最好的选择。

2.最优子结构性质:当一个文艺的最优解包含着它的子问题的最优解时,就称此问题具有最优子结构性质。

我们经常使用的哈弗曼编码算法,求解最小生成树的克鲁斯卡尔算法和普里姆算法,求解图的单源最短路径的迪克斯特拉算法。

4.回溯法

回溯法的基本思想是:包含问题的所有解的解空间树中,按照深度优化搜索的策略,从根结点出发深度探索解空间树。

当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含, 就从该几点出发继续探索下去;如果该结点不包含问题解,那就说明以该结点为根结点的子树一定不包含问题的最终解,因此要跳过对以该结点为根的子树的系统探索,逐层向其祖先结点回溯。这个过程叫做解空间树的“剪枝”操作。

例:N皇后问题的描述:求解如何一个NxN的棋盘上无冲突地摆放N个皇后棋子。在国际象棋中皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平、竖直,以及45°斜线上都不能出现皇后的棋子。

N皇后问题的解法很多,可以用回溯法解决N皇后问题。以四皇后问题为例可以构建出一棵解空间树,通过探索这棵空间树,可以得到四皇后问题的一种或几种解。

方法描述和程序清单:

解决四皇后问题的算法描述如下:

void Queen(int j,int(*Q)[4])
{
  int i,k;
  if(j==4){
      for(k=0;k<4;k++){/*得到了一个解,在屏幕上输出结果*/
      printf("%d",Q[i][k]);
      printf("\n");
    }
    printf("\n");
    getche();
    return;
  }
  for(i=0;i<4;i++){
    if(isCorrect(i,j,Q)){
      Q[i][j] = 1;
      Queen(j+1,Q);
      Q[i][j]= 0;
    }
  }
}

在算法中,用一个二维数组Q[4][4]存放棋盘布局。Q[i][j]=0表示不放置皇后,Q[i][j]=0表示放置皇后。在这里采用了递归回溯方法深度优化搜索解空间树。可以将四皇后问题的全部解找出来。

函数Queen()包含两个参数,参数j的初始值为0,由它可派生出第一个解空间树。j的取值范围是0~3,对应着4棵解空间树。当j=4时,表明已经得到了一个四皇后的解,程序返回。参数(*Q)[4]为指向二维数组每一行的指针。

  在该算法中调用了子函数isCorrect(i,j,Q),它的功能是判断棋盘中Q[i][j]的位置是否可以放置一个皇后。它的算法描述如下:

int isCorrect(int i ,int j ,int (*Q)[4])
{
  int s,t;
  for(s=i,t=0;t<4;t++)
    if(Q[s][t]==1&&t!=j)return 0;//判断行
  for(t=j,s=0;s<3;s++)
    if(Q[s][t]==1&&s!=i)return 0;//判断列
  for(s=i-1,t=j-1;s<3;s++)
    if(Q[s][t]==1&&s!=i)return 0;//判断左上方
  for(s=i+1,t=j+1;s<3;s++)
    if(Q[s][t]==1&&s!=i)return 0;//判断右下方
  for(s=i-1,t=j+1;s<3;s++)
    if(Q[s][t]==1&&s!=i)return 0;//判断右上方
  for(s=i+1,t=j-1;s<3;s++)
    if(Q[s][t]==1&&s!=i)return 0;//判断左下方
return 1;

}

 

5 数值概率算法

数值概率算法大致分为4类:数值概率算法、蒙特卡洛算法、拉斯维加斯算法、舍伍德算法。

数值概率算法常应用与解决数值计算的问题。