合并排序——分治策略

来源:互联网 发布:windows安装淘宝镜像 编辑:程序博客网 时间:2024/06/08 02:51


1、分治法

     将原问题划分成N个规模较小而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。

2、合并排序

      算法描述:     

    

      代码实现     

<span style="font-size:18px;">package com.dataStructure;public class MergeSort {public void mergeSort(int[] A, int p, int r) {if(p<r) {int q=(int) Math.floor((p+r)/2);mergeSort(A, p, q);mergeSort(A, q+1, r);merge(A,p,q,r);}}public void merge(int[] A, int p, int q, int r) {int n1=q-p+1, n2=r-q;int[] L=new int[n1];int[] R=new int[n2];for(int i=0;i<n1;i++){L[i]=A[p+i];}for(int i=0;i<n2;i++){R[i]=A[q+i+1];}int i=0,j=0;for(int k=p; k<=r; k++){if ((i<L.length&&j<R.length)&&(L[i]<=R[j])) {A[k]=L[i];i++;continue;} if((i<L.length&&j<R.length)&&(L[i]>R[j])){A[k]=R[j];j++;continue;}if(i>=L.length&&j<R.length) {A[k]=R[j];j++;continue;}if (j>=R.length&&i<L.length) {A[k]=L[i];i++;continue;}}}public static void main(String[] args) {MergeSort mergeSort = new MergeSort();int[] A=new int[]{1,3,8,9,4,5,6,7,2};mergeSort.mergeSort(A, 0, A.length-1);System.out.println("success");}}</span>

3、大整数乘法

      算法描述:

     

       代码实现:      

<span style="font-size:18px;">package com.bigInteger.util;public class IntegerString {public int string_to_num(String k) {return Integer.parseInt(k);}public String num_to_string(int intValue){return Integer.toString(intValue);}//在字符串str前添加s个零public String stringBeforeZero(String str,int s){String zeroStr="0";for(int i=1; i<s; i++)zeroStr=zeroStr+"0";return zeroStr+str;}//两个大整数字符串相加,超出计算机表示范围的数也能实现相加(本函数可以实现大整数加法运算)public String stringAddstring(String str1,String str2){//假定str1和str2是相等的长度,不相等时在前面自动补零,使两个字符串长度相等if (str1.length() > str2.length()) {str2 = stringBeforeZero(str2,str1.length() - str2.length());}else if (str1.length() < str2.length()) {str1 = stringBeforeZero(str1,str2.length() - str1.length());}String result="0";int flag=0;//前一进位是否有标志,0代表无进位,1代表有进位for(int i=str1.length()-1; i>=0; i--){int c=(str1.charAt(i)-'0')+(str2.charAt(i)-'0')+flag;flag = c/10;//c大于10时,flag置为1,否则为0c %= 10;//c大于10时取模,否则为其本身result=num_to_string(c)+result;}if (0 != flag) //最后一为(最高位)判断,如果有进位则再添一位result=num_to_string(flag)+result;return result.substring(0, result.length()-1);}/*两个大整数字符串相减,超出计算机表示范围的数也能实现相减(在这里比较特殊,第一个参数一定大于第二个参数,因为:a1*b0+a0*b1=(a1+a0)*(b1+b0)-(a1*b1+a0*b0) > 0 ,所以(a1+a0)*(b1+b0) > (a1*b1+a0*b0)这个函数的两个参数,第一个代表的其实就是(a1+a0)*(b1+b0),第二个代表的其实就是(a1*b1+a0*b0)所以本函数里不用考虑最终得到结果为负数的情况,至于计算有关大整数负数相乘的问题可以通过其他途径判断*/public String stringSubtractstring(String str1,String str2){//对传进来的两个数进行修剪,如果前面几位有0则先去掉,便于统一处理while('0'==str1.charAt(0)&&str1.length()>1){str1=str1.substring(1);}while('0'==str2.charAt(0)&&str2.length()>1){str2=str2.substring(1);}//使两个字符串长度相等if (str1.length() > str2.length()){str2 = stringBeforeZero(str2,str1.length() - str2.length());}String result="0";for(int i=str1.length()-1; i>=0; i--){int c=(str1.charAt(i)-'0')-(str2.charAt(i)-'0');if (c < 0) //当不够减时向前一位借位,前一位也不够位时再向前一位借位,依次如下{c +=10;int prePos = i-1; char preChar = str1.charAt(prePos);while ('0' == preChar) {str1=str1.substring(0, prePos)+"9"+str1.substring(prePos+1);prePos -= 1;preChar = str1.charAt(prePos);}char borrow=(char) (str1.charAt(prePos)-1);str1=str1.substring(0, prePos)+Character.toString(borrow)+str1.substring(prePos+1);}result=num_to_string(c)+result;}return result.substring(0, result.length()-1);}//在字符串str后跟随s个零public String stringFollowZero(String str,int s){String zeroStr="0";for(int i=1; i<s; i++)zeroStr=zeroStr+"0";return str+zeroStr;} //分治法大整数乘法实现函数public String IntMult(String x,String y)//递归函数{//对传进来的第一个数进行修剪,如果前面几位有0则先去掉,便于统一处理while ('0' == x.charAt(0)&&x.length()>1){x=x.substring(1);}//对传进来的第二个数进行修剪,如果前面几位有0则先去掉,便于统一处理while ('0' == y.charAt(0)&&y.length()>1){y=y.substring(1);}/*这里的f变量代表在两个数据字符串长度不想等或者不是2的指数倍的情况下,所要统一的长度,这样做是为了让数据长度为2的n次方 的情况下便于利用分治法处理*/int f=4;/*当两字符串中有任意一个字符串长度大于2时都要通过与上面定义的f值进行比较,使其达到数据长度为2的n次方,实现方式是在前面 补0,这样可以保证数据值大小不变*/if (x.length()>2 || y.length()>2) {if (x.length() >= y.length()) //第一个数长度大于等于第二个数长度的情况{while (x.length()>f) //判断f值{f*=2;}if (x.length() != f) {x = stringBeforeZero(x,f-x.length());y = stringBeforeZero(y,f-y.length());}}else//第二个数长度大于第一个数长度的情况{while (y.length()>f) //判断f值{f*=2;}if (y.length() != f) {x = stringBeforeZero(x,f-x.length());y = stringBeforeZero(y,f-y.length());}}} if (1 == x.length()) //数据长度为1时,在前面补一个0(这里之所以会出现长度为1的数据是因为前面对数据修剪过){ x=stringBeforeZero(x,1);}if (1 == y.length()) //数据长度为1时,在前面补一个0(这里之所以会出现长度为1的数据是因为前面对数据修剪过){y=stringBeforeZero(y,1);} if (x.length() > y.length()) //最后一次对数据校正,确保两个数据长度统一{ y = stringBeforeZero(y,x.length()-y.length());}if (x.length() < y.length()) //最后一次对数据校正,确保两个数据长度统一{x = stringBeforeZero(x,y.length()-x.length());}int s = x.length();     String a1="0",a0="0",b1="0",b0="0";     if( s > 1)     {         a1 = x.substring(0,s/2);         a0 = x.substring(s/2);         b1 = y.substring(0,s/2);         b0 = y.substring(s/2);     } String result;if( s == 2) //长度为2时代表着递归的结束条件    {     int na = string_to_num(a1);         int nb = string_to_num(a0);          int nc = string_to_num(b1);         int nd = string_to_num(b0);        result = num_to_string((na*10+nb) * (nc*10+nd));     } else{//长度不为2时利用分治法进行递归运算    /***************************************************    小提示:    c = a*b = c2*(10^n) + c1*(10^(n/2)) + c0;    a = a1a0 = a1*(10^(n/2)) + a0;    b = b1b0 = b1*(10^(n/2)) + b0;    c2 = a1*b1;  c0 = a0*b0;    c1 = (a1 + a0)*(b1 + b0)-(c2 + c0);    ****************************************************/    String c2 = IntMult(a1,b1);// (a1 * b1)        String c0 = IntMult(a0,b0);// (a0 * b0)        String c1_1 = stringAddstring(a1,a0);// (a1 + a0)        String c1_2 = stringAddstring(b1,b0);// (b1 + b0)        String c1_3 = IntMult(c1_1,c1_2);// (a1 + a0)*(b1 + b0)        String c1_4 = stringAddstring(c2,c0);// (c2 + c0)        String c1=stringSubtractstring(c1_3,c1_4);// (a1 + a0)*(b1 + b0)-(c2 + c0)    String s1=stringFollowZero(c1,s/2);// c1*(10^(n/2))    String s2=stringFollowZero(c2,s);// c2*(10^n)        result = stringAddstring(stringAddstring(s2,s1),c0);// c2*(10^n) + c1*(10^(n/2)) + c0    }return result;}public static void main(String[] args) {IntegerString bigIntMul=new IntegerString();String r=bigIntMul.IntMult("1111111111999999999888888888555555555444444444777777777222222222333333333666666666","999999999888888888777777777444444444555555555666666666111111111222222222333333333");while('0'==r.charAt(0)&&r.length()>1){r=r.substring(1);}System.out.println(r);}}</span>
3、快速排序

     算法描述:

     

     代码实现:

    

package com.dataStructure;public class QuickSort {    //快速排序     public void quick_sort(int s[], int l, int r)      {          if (l < r)          {              //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1              int i = l, j = r, x = s[l];              while (i < j)              {                  while(i < j && s[j] >= x) // 从右向左找第一个小于x的数                      j--;                    if(i < j)                       s[i++] = s[j];                                    while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数                      i++;                    if(i < j)                       s[j--] = s[i];              }              s[i] = x;              quick_sort(s, l, i - 1); // 递归调用               quick_sort(s, i + 1, r);          }      }  public static void main(String[] args) {QuickSort quickSort = new QuickSort();int[] A=new int[]{5,3,8,9,4,1,6,7,2};quickSort.quick_sort(A, 0, A.length-1);}}


0 0