算法

来源:互联网 发布:seven stars烟淘宝 编辑:程序博客网 时间:2024/06/10 01:28

      一个用算法实现的程序会耗费两种资源:处理时间和内存。很显然,一个好的算法应该耗费时间少、所用内存低,但是实际上往往不能两全其美。

     算法的类型分为如下几种:

     1、贪婪算法:每一步所做的都是当前最紧急、最有利的,不会考虑后果,直到完成任务。这种算法的稳定性很差,很容易带来严重成果,但是如果方向正确,该算法也是高效的。

     2、分治算法:该算法就是将一个大问题分解成许多小问题,然后单独处理这些小问题,最终将结果结合起来形成对整个问题的解决方案。当子问题和总问题类型类似时,该算法很高效,递归就属于该算法。

     3、回溯算法:也可以称为“排除算法”,是一种组织好的试错法。某一点如果有多个选择,则任意选择一个,如果不能解决问题则退回选择另一个,直到找到正确的选择。这种算法的效率很低,除非运气好,比如迷宫就可以使用这种算法来实现。

     衡量算法是否高效主要从以下几方面分析:

     1、简单性和清晰度

     2、空间效率

     3、时间效率

     要衡量算法的效率,关注如下几个方面:

     1、测量执行时间:Java中可使用System.currentTimeMillis()获得毫秒数,可在需要测量的代码前后获得开始、结束时间,两者相减就是耗费的毫秒数。

     2、指令计数:指编写算法的代码,对一个算法的实现代码计算执行指令次数。

     3、测量内存使用率:算法中包含的对象和引用书目,其越多则内存使用越高,反之越低。

     查找算法:

    (1)线性查找:从数组的第一个元素开始查找,并将其与查找值比较,如果相等则停止,否则继续下一个元素查找,直到找到匹配值。要求被查找的数组中的元素是无序的、随机的。

     static boolean linearSearch(int target,int[] array){

            int len=array.length;

           for(int i=0;i<len;i++){

                 if(array[i]==target){

                      return true;

                 }

            }

            return false;

      }

     (2)二分查找:假设被查找数组中的元素是升序排列的,那么查找时,首先会直接到数组的中间位置(数组长度/2),并将中间值和查找值比较,如果相等则返回;否则,如果当前元素值小于查找值,则继续在数组的后面一半查找,如果当前元素值大于查找值,则继续在数组的前面一半查找,直到找到目标值或者无法再二分数组时停止。二分查找只是针对有序排列的各种数组或集合。

    static boolean binarySearch(int target,int[] array){

           int front=0;

           int tail=array.length-1;

           //判断子数组是否能再次二分

           while(front<=tail){

                 int middle=(front+tail)/2;

                 if(array[middle]==target){

                      return true;

                 }

                else if(array[middle]>target){

                      tail=middle-1;

                }

                else{

                      front=middle+1;

               }

         }

         return false;

 }

     排序算法:

   (1)选择排序:首先在数组中查找最小值,如果该值不在第一个位置,那么将其和处在第一个位置的元素交换,然后从第二个位置重复此过程,将剩下元素中的最小值交换到第二个位置,当到最后一位时,数组排序结束。

static void selectionSort(int[] array){

      for(int i=0;i<array.length-1;i++){

             int min_idx=i;

             for(int j=i+1;j<array.length;j++){

                   if(array[j]<array[min_idx]){

                         min_idx=j;

                   }

              }

             if(min_idx !=i){

                    int temp=array[min_idx];

                   array[min_idx]=array[i];

                   array[i]=temp;

             }

       }

}

     假设数组大小为n,外循环共执行n-1次;那么第一次执行外循环时,内循环将执行n-1次;第二次执行外循环时内循环将执行n-2次,最后一次执行外循环时内循环将执行1次,则增长函数为:(n-1)+(n-2)+...+1=n(n-1)/2=1/2*n^2+1/2*n,即可得出复杂度为O(n^2)。当数组非常大时,用于元素交换的开销相当大。

     (2)冒泡排序:若左边的值小于或等于右边的值,则这两个值的位置不变。右边的值继续和下一个值做比较,重复此操作,知道比较到最后一个值。

static void bubbleSort(int[] array){

      int out,in,len;

      len=array.length;

      for(out=len-1;out>1;out--){

            boolean flag=false;

            for(in=0;in<out;in++){

                  if(array[in]>array[in+1]){

                        int temp=array[in];

                        array[in]=array[in+1];

                        array[in+1]=temp;

                        flag=true;

                   }

             }

             if(! flag){

                    break;

             }

      }

}

     (3)插入排序:对于欲排序的元素以插入的方式寻找该元素的适当位置,以达到排序的目的。优点是利用一个个元素的插入比较将元素放入适当的位置,所以是一种很简单的排序方式。但因每次排序都要与之前已排序好的元素作比较,故需花费较长的排序时间。

static void insertSort(int[] array){

      int in,out,len;

     len=array.length;

     for(out=1;out<len;out++){

           int temp=array[out];

           in=out;

           while(in>0&&array[in-1]>=temp){

                 array[in]=array[in-1];

                 --in;

           }

           array[in]=temp;//该数据要插入的位置

     }

}

     递归算法:

     斐波那契递归参考代码如下:

static int fibonacci(int n){

       if(n<=2){

             return 1;

      }else{

             return fibonacci(n-1)+fibonacci(n-2);

     }

}

原创粉丝点击