码迷,mamicode.com
首页 > 编程语言 > 详细

五大算法之分治算法

时间:2015-02-12 00:32:52      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

一、基本思想

       当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。

二、二分法

       利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索。

三、解题步骤

分治法解题的一般步骤:
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
(2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

技术分享

 

四、应用场景

运用分治策略解决的问题一般来说具有以下特点:
1、原问题可以分解为多个子问题
这些子问题与原问题相比,只是问题的规模有所降低,其结构和求解方法与原问题相同或相似。
2、原问题在分解过程中,递归地求解子问题
由于递归都必须有一个终止条件,因此,当分解后的子问题规模足够小时,应能够直接求解。
3、在求解并得到各个子问题的解后
应能够采用某种方式、方法合并或构造出原问题的解。
不难发现,在分治策略中,由于子问题与原问题在结构和解法上的相似性,用分治方法解决的问题,大都采用了递归的形式。在各种排序方法中,如归并排序、堆排序、快速排序等,都存在有分治的思想。

 

五、示例

1)二分搜索

二分搜索的前提是“数据必须有序”,也就是先要排序好。

(1)binarySearch.cpp

  1. #include <stdio.h>  
  2.   
  3. /// <summary>  
  4. /// 分治算法之二分法查找  
  5. /// </summary>  
  6. /// <param name="array">数组指针</param>  
  7. /// <param name="len">数组长度</param>  
  8. /// <param name="value">查询的值</param>  
  9. /// <returns>查询到的下标</returns>  
  10. int binarySearch(int *array, int len, int value)  
  11. {  
  12.     int low = 0;  
  13.     int high = len-1;  
  14.     //index : 将返回的下标  
  15.     int index = -1;  
  16.   
  17.     while(low <= high)  
  18.     {  
  19.         //二分,得到中间位置  
  20.         int mid = (high + low)/2;  
  21.   
  22.         //找到该数  
  23.         if (value == array[mid])  
  24.         {  
  25.             index = mid;  
  26.             break;  
  27.         }  
  28.         else if (array[mid] < value)  
  29.         {//值位于右边  
  30.             low = mid + 1;  
  31.         }  
  32.         else  
  33.         {//值位于左边  
  34.             high = mid - 1;  
  35.         }  
  36.     }  
  37.   
  38.     return index;  
  39. }  
  40. /// <summary>  
  41. ///  主函数  
  42. /// </summary>  
  43. /// <returns></returns>  
  44. int main(void)  
  45. {  
  46.     int array[] = {0,1,2,3,4,5,6,7,8,9};  
  47.     //len : 数组长度  
  48.     int len = sizeof(array)/sizeof(array[0]);  
  49.     int value = array[5];  
  50.     //index 查找位置  
  51.     int index = binarySearch(array, len,value);  
  52.   
  53.     //index = -1 :未找到该值  
  54.     if (-1 != index)  
  55.     {  
  56.         printf("the value is %d\n",array[index]);  
  57.     }  
  58.   
  59.     return 0;  
  60. }  

(2)binarySearchDemo.java

  1. package algorithm.qdj.div;  
  2.   
  3. /** 
  4.  * @author qingdujun 
  5.  * 
  6.  */  
  7. public class binarySearchDemo {  
  8.   
  9.     public static void main(String[] args) {  
  10.   
  11.         int[] array= new int[]{0,1,2,3,4,5,6,7,8,9};  
  12.         int value = array[5];  
  13.           
  14.         int index = binarySearch(array, value);  
  15.         if (index != -1) {  
  16.             System.out.println("this value is "+array[index]);  
  17.         }  
  18.     }  
  19.     /** 
  20.      * 分治算法之二分法查找 
  21.      * @param array 数组引用 
  22.      * @param value 查找值 
  23.      * @return 查找到的位置 
  24.      */  
  25.     private static int binarySearch(final int[] array,final int value)  
  26.     {  
  27.         int low = 0;  
  28.         int high = array.length-1;  
  29.         //index : 将返回的下标  
  30.         int index = -1;  
  31.   
  32.         while(low <= high)  
  33.         {  
  34.             //二分,得到中间位置  
  35.             int mid = (high + low)/2;  
  36.   
  37.             //找到该数  
  38.             if (value == array[mid])  
  39.             {  
  40.                 index = mid;  
  41.                 break;  
  42.             }  
  43.             else if (array[mid] < value)  
  44.             {//值位于右边  
  45.                 low = mid + 1;  
  46.             }  
  47.             else  
  48.             {//值位于左边  
  49.                 high = mid - 1;  
  50.             }  
  51.         }  
  52.   
  53.         return index;  
  54.     }  
  55. }  

2)大数乘法

大数乘法,实现原理就是用计算机模拟人工手动计算,比如:123 x 45,只要会123x5那么,123x4就是一样的计算原理。

技术分享

BigDiv.cpp

  1. //大数乘法  By:我愛編程   
  2. //2015年1月26日13:49:27  
  3. #include <iostream>  
  4. #include <string>  
  5. using namespace std;  
  6.   
  7. /// <summary>  
  8. /// 大数乘法  
  9. /// </summary>  
  10. /// <param name="num1">被乘数</param>  
  11. /// <param name="num2">乘数</param>  
  12. string BigDiv(string num1, string num2)  
  13. {  
  14.     //len1获得被乘数的长度,用于动态开辟缓存空间  
  15.     int len1 = num1.size();  
  16.     //len2乘数的长度  
  17.     int len2 = num2.size();  
  18.     //需要开辟缓存空间大小  
  19.     int len = len1+len2;  
  20.     //buf缓存计算数据  
  21.     int *buf = new int[len];  
  22.     //将buf数组内容全部初始化为0,你也可以用for循环  
  23.     memset(buf,0,sizeof(int)*(len) );  
  24.       
  25.     //---------模拟乘法--------  
  26.     //--i比i--效率更高,t用于配合乘数偏移  
  27.     for (int it = 0,i = len2-1; i >= 0; --i,++it)  
  28.     {//i 循环为乘数,初始位置为最末尾  
  29.         for (int jt = 0,j = len1-1; j >= 0; --j,++jt)  
  30.         {//j 循环为被乘数,初始位置为最末尾  
  31.             //注意存储位置,buf数组,从后往前存放内容  
  32.             buf[len-1-it-jt] += ( (num1[j]-‘0‘)*(num2[i]-‘0‘) );  
  33.         }  
  34.     }  
  35.       
  36.     //----------模拟进位--------  
  37.     for (int k = len-1; k > 0; --k)  
  38.     {  
  39.         if (buf[k] > 9)  
  40.         {  
  41.             //进位  
  42.             buf[k-1] += (buf[k] / 10);   
  43.             buf[k] = (buf[k] % 10);  
  44.         }  
  45.     }  
  46.   
  47.     //----过滤buf[]前面无用的0-----  
  48.     //index标识第一个不为0的位置  
  49.     int index = 0;  
  50.     while ( 0 == buf[index] )  
  51.     {  
  52.         ++index;  
  53.     }  
  54.   
  55.     //-----将数字转化为string,返回给main()----  
  56.     string result;    
  57.     for (int x = index; x < len; ++x)  
  58.     {  
  59.         //string重载了+=,其效果就是直接追加在尾部  
  60.         result += (buf[x]+‘0‘);  
  61.     }  
  62.   
  63.     return result;  
  64. }  
  65. /// <summary>  
  66. /// 交换两数,使num1>num2  
  67. /// </summary>  
  68. /// <param name="num1"></param>  
  69. /// <param name="num2"></param>  
  70. void swap(string &num1, string &num2)  
  71. {  
  72.     string buf;  
  73.     if ( ( num1.size() <= num2.size() ) && (num1 < num2))  
  74.     {  
  75.         buf = num1;  
  76.         num1 = num2;  
  77.         num2 = buf;  
  78.     }  
  79. }  
  80.   
  81. int main(void)  
  82. {  
  83.     string num1,num2;  
  84.   
  85.     //输入两个大数,这里用C++string可以支持动态输入  
  86.     cin>>num1>>num2;  
  87.     swap(num1,num2);  
  88.   
  89.     cout<<BigDiv(num1,num2)<<endl;  
  90.   
  91.     return 0;  
  92. }  

 

3)快速排序

 

快速排序,就三步:

1)选择一个基准Select

2)将该Select摆放在合适的位置

3)重复1、2步骤

注意:选择的基准(Select),这个是自己随便选择的。所谓合适的位置,就是要使该位置前面的数字全部小于(大于)Select,后面的数字全部大于(小于)Select,同时一旦确定了Select的摆放位置,以后永远不再挪动Select。比如:下图中选择第一个数字9为基准,那么就要把9摆放在合适的位置(使9前面的数字全部小于9,后面的数字全部大于9,但不一定要有序)。下图为一趟对9的快速排序,直接找到了9应该摆放的位置。

技术分享

 

  1. //快速排序 By 我愛編程 
  2. //2015年1月26日14:10:47  
  3. #include <stdio.h>  
  4.   
  5. void Qsort(int a[], int low, int high)  
  6. {  
  7.     int Select = a[low];            
  8.     int i = low, j = high;    //确保low,high值不变  
  9.   
  10.     if (i >= j)  
  11.         return;  
  12.     else  
  13.     {  
  14.         while (i < j)          //i < j 确保两个寻找下标不冲突  
  15.         {  
  16.             while (a[j] > Select && i < j)  //从右往左找比Select小的值  
  17.                 --j;  
  18.             a[i] = a[j];                    //将该值放在上一步空出的位置  
  19.             while (a[i] <= Select && i < j) //从左往右找比Select大的值  
  20.                 ++i;  
  21.             a[j] = a[i];                    //将该值放在上一步空出的位置  
  22.         }  
  23.     }  
  24.     a[i] = Select;   //或者a[j] = Select; 此时i == j,将该数放入,此时Select已经排放好  
  25.   
  26.     Qsort(a, low, i-1);   //先排左边,i-1和j-1是一样的  
  27.     Qsort(a, i+1, high);  //排右边  
  28. }  
  29.   
  30. int main()  
  31. {  
  32.     int i, a[5] = {13,4,7,8,2};  
  33.   
  34.     Qsort(a, 0, 4);  
  35.     for (i = 0; i < 5; ++i)  
  36.         printf("%d ",a[i]);  
  37.   
  38.     return 0;  
  39. }  

未完待续,示例更新中……

六、参考文献:

百度百科,分治算法,http://baike.baidu.com/view/1650802.htm

五大算法之分治算法

标签:

原文地址:http://www.cnblogs.com/qingdujun/p/4287093.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!