合并排序——分治策略


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,否则为0
			c %= 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);
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值