`
剑锋无刃
  • 浏览: 34336 次
  • 性别: Icon_minigender_1
  • 来自: 长沙市
最近访客 更多访客>>
社区版块
存档分类
最新评论

利用分治法排序

阅读更多

分治法:

有很多算法在结构上是递归的,为了解决这一给定的问题,算法要一次或者多次的递归调用其自身来解决问题,通常这样的算法会用到分治法,那么什么是分治法呢?分治法就是将一个规模很大的问题,分解为很多的可以很用以就得到解决的子问题,而且这些子问题与原问题有着相似的结构,然后,分别求解这些子问题的解,最后,合成这些子问题的解,从而得到原问题的解的方法。

 

 

分治策略:(三步走)

分解(Divide):将原问题分解为与原问题相似的一系列子问题的过程;

解决(Conquer):递归的解决各个子问题,若是子问题足够小,则就可直接求解;

合并(Combine):将子问题的解合并成为原问题的解。

       注意:关于如何将原问题分解为子问题的情况,我们应该具体情况,具体分析,因为分成不同的等分时,可能会影响到时间复杂度。所以,分子问题应该是分治法的难点。

 

 

????看到上面的描述,没接触过算法的朋友,可能还是不清楚,那么我们举个生活中的例子,就很用以理解了。

 

举例(扑克牌排序):

假设我们的桌子上有两堆牌A,B,每一堆都是排好序的,最小的牌在最上面一张。现在,我们希望将这两堆牌何在一起,并进行排序,面朝下的放在桌子上。那么,我们可以这样做,同时拿起两堆牌A,B中的第一张,进行比较,选取小的一张,放在新的地方,然后,(假设是A堆中的第一张牌小)我们再从选择的那A堆,抽出第二张牌,与手中的B堆的第一张牌进行比较,同样小的拿出。(如果此时是B得小,我们就得再从B堆中抽一张牌与A堆的第二张比较,同样拿出小的牌),一直进行下去,直到手上剩下最后一张牌。就是最大的牌了。

       分治法其实就是先将大规模数据,进行分组,并将很容易排序的组别时进行排序,之后,就跟那排好序的那堆牌一样的做法进行合并排序。

 

如果大家还不明白,请看下图。

图形说明:



 伪代码实现:

Merge-Sort(A,p,r)

           if  p < r
                    then  q<---(向下取整)(p+q)/2
                             Menge-Sort(A,p,q);
                             Menge-Sort(A,q+1,r);
                             Menge(A,p,q,r);

         Merge(A,p,q,r)

      n1<-----q-p+1
      n2<------r-q
      creat arrays left[0......,n1-1] and right [0,......n2-1]
      for i<---- 0 to n1-1
              do left[i] <----A[p+i]
      for j<---- 0 to n2-1
              do right[j] <---A[q+j+1]
       i<---- 0
       j<---- 0
       for k<----p to r   (i<n1 and j<n2)
                do if left[i]<=right[j]
                          then A[k] <----left[i]     i++
                      else
                          then A[k] <----right[j]   j++
        if i==n1
                while  j != n2
                          array[k] = right[j];
                          ++k;
                          ++j;
        if j==n2
                while  i != n1
                          array[k] = left[i];
                          ++k;
                          ++i;
                      
 
 

Java代码实现:

方法1:

public class MergeSort
{
	/**
	 * 主方法
	 */
	public static void main(String []args)
	{
		int []array={5,8,4,6,2,3,1,9};
		int alen=array.length;
		System.out.println("未排序前的顺序:");
		for(int i=0;i<alen;i++)
		{
			System.out.print(" "+array[i]+" ");
		}
		
		MergeSortWay(array,0,alen-1);
		
		System.out.println("\n排序后的顺序:");
		for (int i = 0; i < alen; i++)
		{
			System.out.print(" "+array[i]+" ");
		}
	}
	/**
	 * 分治法
	 */
	public static void MergeSortWay(int array[],int p,int r)
	{
		if(p<r)
		{
			int q=(p+r)/2;
			MergeSortWay(array,p,q);
			MergeSortWay(array,q+1,r);
			MergeWay(array,p,q,r);
		}
	}
	/**
	 * 合并的方法
	 */
	public static void MergeWay(int array[],int p,int q,int r)
	{
		int n1=q-p+1;
		int n2=r-q;
		int left[]=new int [n1];
		int right[]=new int [n2];
		for(int i=0;i<n1;i++)
			left[i]=array[p+i];
		for(int j=0;j<n2;j++)
			right[j]=array[q+j+1];
		
		int i,j,k;
		for( i=0,j=0,k=p;k<array.length&&i<n1&&j<n2;k++)
		{
			if(left[i]<=right[j])
			{
				array[k]=left[i];
				i++;
			}
			else if(right[j]<=left[i]) 
			{
				array[k]=right[j];	
				j++;
			}		
		}
		if (i == n1)
          while (j != n2) 
          {
              array[k] = right[j];
              ++k;
              ++j;
          }
      if (j == n2)
          while (i != n1) 
          {
              array[k] = left[i];
              ++k;
              ++i;
          }
		
	}
}

 方法2:

public class MergeSort 
{
    public static void main(String args[]) 
   {
        int[] num = {5, 8, 4 , 6, 2, 3, 1, 9};
        System.out.println("未排序前:");
        for (int i=0;i<num.length;i++)
            System.out.print(num[i] + "   ");
        System.out.println();
        
        mergesort(num, 0, num.length-1);  
        System.out.println("经排序后:");
        for (int i=0;i<num.length;i++)
            System.out.print(num[i]+"   ");
        System.out.println();                
    }
    
    public static void merge(int[] A, int p, int q, int r)
   {
        int n1 = q - p + 1;    
        int n2 = r - q;        
        int []Left = new int[n1];     
        int []Right = new int[n2];   
        
        int i = 0;
        int j = 0;
        while (i != n1) 
       {
            Left[i] = A[p + i];
            ++i;
        }
        while (j != n2) 
       {
            Right[j] = A[q + j + 1];
            ++j;
        }
        
        i = j = 0;
        int k = p;
        while (i != n1 && j != n2)
       {
            if (Left[i] <= Right[j]) 
           {
                A[k] = Left[i];
                ++i;
            }
            else 
           {
                A[k] = Right[j];
                ++j;
            }
            ++k;
        }
        if (i == n1)
            while (j != n2)
           {
                A[k] = Right[j];
                ++k;
                ++j;
            }
        if (j == n2)
            while (i != n1) 
           {
                A[k] = Left[i];
                ++k;
                ++i;
            }
    }    
    
    public static void mergesort(int[] A, int p, int r)
   {
        if (p < r)
       {
            int q = (p + r) / 2;
            mergesort(A, p, q);
            mergesort(A, q+1, r);
            merge(A, p, q, r);
        }
    }
}

 输出结果:

未排序前的顺序:

 5  8  4  6  2  3  1  9 

排序后的顺序:

 1  2  3  4  5  6  8  9 

  • 大小: 51.8 KB
0
0
分享到:
评论

相关推荐

    实验4 分治法1

    1. **理解问题和算法**:仔细分析每个问题,理解它们的性质,以及如何利用分治法解决。 2. **编程实现**:根据理解编写代码,确保每个问题的解决方案都基于分治策略。 3. **上机调试**:运行程序,检查其是否符合...

    java编程实现分治法归并排序

    归并排序是一种非常实用的排序算法,它利用分治策略高效地对数组进行排序。Java代码示例展示了如何实现归并排序,并通过实际运行结果验证了算法的有效性。对于理解和实现高效排序算法来说,归并排序是一个很好的起点...

    分治法:快速排序的示例程序

    它的核心思想是分治法(Divide and Conquer),即将一个大问题分解为两个或更多的小问题来解决。分治法通常包括三个步骤:分解、解决和合并。在快速排序中,这三步的具体应用如下: 1. **分解**: 快速排序首先...

    求一组数组的两个最大值和两个最小值 分治法

    ### 使用分治法求解数组中的两个最大值与两个最小值 #### 一、问题背景与目标 在算法设计实验中,有一道题目的要求是使用分治法(Divide and Conquer)来求解一个数组中的两个最大值与两个最小值。与蛮力法不同,...

    分治法求两个大整数相乘

    分治法常用于排序(如快速排序)、查找(如二分查找)等场景,但对于大整数的乘法也同样适用。 #### 三、算法设计思想 对于两个大整数的乘法问题,我们可以采用分治法的思想将其分解为更小规模的乘法问题。具体...

    分治法快速排序算法QuickSort

    总的来说,快速排序是一种非常重要的排序算法,它充分利用了分治法的优势,通过巧妙的分区策略和递归实现,使得在大多数情况下都能获得高效的表现。理解和掌握快速排序对于提升编程能力,特别是在处理数据处理和算法...

    分治法应用(二分查找归并排序快速排序比赛日程安排)

    4. **比赛日程安排**:虽然这个主题通常不直接与传统的分治法关联,但我们可以将其视为一个优化问题,利用类似贪心算法或动态规划的方法来解决。例如,可以通过优先考虑冲突最少的比赛或优先安排高优先级的比赛来...

    合并排序(分治策略)报告.doc

    分治法的基本策略是将一个难以直接解决的大问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题,再将子问题的解组合得到原问题的解。在合并排序中,这个过程具体表现为: 1. **问题描述**: 合并排序...

    分治合并排序代码

    分治法是计算机科学中解决问题的一种通用方法,它将一个大问题分解成若干个规模较小、相互独立、与原问题形式相同的子问题,然后分别解决子问题,最后将子问题的解组合成原问题的解。在合并排序中,这一思想被很好地...

    分治法-中位数

    - 接下来是核心逻辑部分,即利用分治法逐步缩小问题规模,直至找到中位数。 - 最后,输出最终计算出的中位数。 #### 总结 本题利用了分治法的思想解决了两个有序数组合并后的中位数问题。通过不断地缩小问题的规模...

    分治法求最近点对

    **标题解析:**“分治法求最近点对”指的是使用分治策略来解决寻找二维空间中距离最近的两个点的问题。在计算机科学中,分治法是一种将复杂问题分解成更小、易于处理的部分的方法,然后分别解决这些部分,最后合并...

    分治法求众数.doc

    总结一下,本实验通过分治法和快速排序的启发,设计了一个高效的求解众数的算法。它避免了完全排序,减少了时间复杂度,同时利用递归策略缩小搜索范围,提高了算法效率。在实际编程中,这种思想可以广泛应用于解决...

    分治法合并排序算法实现merge

    在本案例中,我们将讨论如何利用分治法实现合并排序(Merge Sort),这是一种效率较高的排序算法,其时间复杂度为O(n log n)。 合并排序的基本思想是将原始数组分为两个相等(或接近相等)的部分,对每一部分分别...

    分治法求最大值的C++实现

    本文将详细探讨如何利用分治法在C++中实现寻找数组中的最大值。 ### 分治法原理 分治法的基本思想是将原问题划分为两个或更多的相同或相似的子问题,递归地求解子问题,然后将子问题的解合并得到原问题的解。这一...

    分治法大整数乘法课件

    例如,Karatsuba算法利用分治策略,将两个n位的大整数乘法转化为三个较小的乘法运算,其时间复杂度为O(n^1.585),比朴素的O(n^2)方法有显著提升。 **4. Strassen矩阵乘法** Strassen算法是分治法在矩阵乘法中的应用...

    算法设计策略 - 05-2 分治法.pdf

    此外,归并排序和快速排序也是应用分治法的典型排序算法,它们都利用了分治法将数组分为更小的片段,递归排序后再合并。 降低复杂度的途径是分治法设计中的另一个关键点。通过合理地划分子问题,可以减少不必要的...

    分治法Solution.zip

    利用分治法,我们可以将点集分成两半,分别计算左半部分和右半部分的最近点对,然后比较跨越分割线的点对与这两部分内部的最近点对,找到全局的最小距离。这样,时间复杂度可以降低到O(n log n)。 压缩包中的...

    分治法解方程_分治法_

    分治法在许多其他领域也有广泛应用,如排序问题(如快速排序、归并排序)、最短路径问题(Floyd-Warshall算法)、矩阵乘法(Strassen算法)、大整数乘法(Karatsuba算法)等。它强调了问题的结构性和递归性,使得...

    分治法选讲=课件

    ### 分治法选讲知识点详解 #### 一、分治法概述 ...通过快速排序和二分法等经典算法,我们可以看到分治法在提高算法效率方面的重要作用。理解并掌握分治法的核心思想和应用场景,对于解决实际问题具有重要意义。

    分治法求解序列最大最小元素【算法设计与分析】

    此外,分治法还可以应用于许多其他领域,如排序(快速排序、归并排序)、查找(二分查找)、矩阵乘法(Strassen算法)、大整数乘法(Karatsuba算法)等。它提供了一种通用的解决问题的方法论,对于学习和理解算法...

Global site tag (gtag.js) - Google Analytics