热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java编写分治策略算法

**分治策略运用练习**一、实验目的本次实验是针对分治策略运用的算法设计及应用练习,旨在加深学生对该部分知识点的理解,提高学生运用该部分知识解决问题的能力。二、实验项目1.对用户输

**分治策略运用练习**

一、实验目的
本次实验是针对分治策略运用的算法设计及应用练习,旨在加深学生对该部分知识点的理解,提高学生运用该部分知识解决问题的能力。

二、 实验项目
1.对用户输入的杂乱无序的数字序列按照由小到大的顺序排序。要求分别运用合并排序和快速排序完成该题目要求。
2.棋盘覆盖问题。(要求N可由用户输入)

三、实验过程
(一)题目一:数字排序



  1. 题目分析
    用合并排序和快速排序的方法使得杂乱无序的数字序列按照由小到大的顺序排序。



  2. 算法构造
    在此论证算法设计中的一些必要的设计依据。
    (1)在保证元素多于一个的同时,取中点把元素分成两个子序列,然后将它们排好序之后进行合并:
    if (left Type* b = new Type[right - left + 1];
    int i = (left + right) / 2;
    MergeSort(a, left, i);
    MergeSort(a, i + 1, right);
    Merge(a, b, left, i, right);
    Copy(a, b, left, right);}
    (2)从第一个数据开始依次与其它的数据比较,比它小的放左边,比它大的放右边,然后在两个子序列中用同样的方法进行数据比较:
    while (i != j){
    while (a[j] >= t && j > i)
    j–;
    if (j > i)
    a[i++] = a[j];
    while (a[i] <&#061; t && j > i)
    i&#043;&#043;;
    if (j > i)
    a[j–] &#061; a[i];}



  3. 算法实现
    程序源代码&#xff08;请写入必要的注释&#xff09;。
    &#xff08;1&#xff09;合并排序
    package com.cn;
    import java.util.Arrays;
    import java.util.Scanner;
    public class OrderMerging {
    static int [] num&#061;new int[10];
    private static void FenZhi(int[] array,int left,int right,int []temp){
    if(left int mid &#061; (left&#043;right)/2;
    FenZhi(array,left,mid,temp);//左边合并排序&#xff0c;使得左边的集合有序排列
    FenZhi(array,mid&#043;1,right,temp);//右边合并排序&#xff0c;使得右边的集合有序排列
    orderMerging(array,left,mid,right,temp);//将两个有序子数组合并操作
    }
    }
    public static void BuiltArray(int []array){
    int []temp &#061; new int[array.length];//在排序前&#xff0c;先建立一个定长的数组&#xff0c;简化实现过程
    FenZhi(array,0,array.length-1,temp);
    }
    private static void orderMerging(int[] array,int left,int mid,int right,int[] temp){
    int i &#061; left;//左哨兵
    int j &#061; mid&#043;1;//分割之后的右哨兵
    int t &#061; 0;//识别数组中位置的哨兵
    while (i<&#061;mid && j<&#061;right){
    if(array[i]<&#061;array[j]){
    temp[t&#043;&#043;] &#061; array[i&#043;&#043;];
    }else {
    temp[t&#043;&#043;] &#061; array[j&#043;&#043;];
    }
    }
    while(i<&#061;mid){//将左边剩余元素放入temp中
    temp[t&#043;&#043;] &#061; array[i&#043;&#043;];
    }
    while(j<&#061;right){//将右序列剩余元素放入temp中
    temp[t&#043;&#043;] &#061; array[j&#043;&#043;];
    }
    t &#061; 0;
    //将temp中的元素全部合并到原数组中
    while(left <&#061; right){
    array[left&#043;&#043;] &#061; temp[t&#043;&#043;];
    }
    }

    public static void main(String []args){
    System.out.println(“请输入无序的数字串&#xff1a;”);
    Scanner scan&#061;new Scanner(System.in);
    for(int i&#061;0;i<&#061;9;i&#043;&#043;){
    num[i]&#061;scan.nextInt();
    }
    System.out.println(“排序后的数列如下&#xff1a;”);
    BuiltArray(num);
    System.out.println(Arrays.toString(num));

    }
    }



&#xff08;2&#xff09;快速排序
package com.cn;

public class QuickSort {

//arr 需要排序的数组
//low 开始时最左边的索引&#061;0
//high 开始时最右边的索引&#061;arr.length-1
public static void quickSort(int[] arr,int low,int high){
int i,j,temp,t;
if(low>high){
return;
}
i&#061;low;//左边哨兵的索引
j&#061;high;//右边哨兵的索引
//temp就是基准位
temp &#061; arr[low];//以最左边为 基准位

while (i //先看右边&#xff0c;依次往左递减
//先从右往左找一个小于 基准位的数
//当右边的哨兵位置所在的数>基准位的数 时
//继续从右往左找&#xff08;同时 j 索引-1&#xff09;
//找到后会跳出 while循环
while (temp<&#061;arr[j]&&i j--;
}
//再看左边&#xff0c;依次往右递增
//步骤和上面类似
while (temp>&#061;arr[i]&&i i&#043;&#043;;
}
//如果满足条件则交换
if (i

//z、y 都是临时参数&#xff0c;用于存放 左右哨兵 所在位置的数据
int z &#061; arr[i];
int y &#061; arr[j];

// 左右哨兵 交换数据&#xff08;互相持有对方的数据&#xff09;
arr[i] &#061; y;
arr[j] &#061; z;
}
}

//这时 跳出了 “while (i //说明 i&#061;j 左右在同一位置
//最后将基准为与i和j相等位置的数字交换
arr[low] &#061; arr[i];//或 arr[low] &#061; arr[j];
arr[i] &#061; temp;//或 arr[j] &#061; temp;

//i&#061;j
//这时 左半数组<(i或j所在索引的数)<右半数组
//也就是说(i或j所在索引的数)已经确定排序位置&#xff0c; 所以就不用再排序了&#xff0c;
// 只要用相同的方法 分别处理 左右数组就可以了

//递归调用左半数组
quickSort(arr, low, j-1);
//递归调用右半数组
quickSort(arr, j&#043;1, high);
}
public static void main(String[] args){
int[] arr &#061; {10,7,2,4,7,62,3,4,2,1,8,9,19};
quickSort(arr, 0, arr.length-1);
for (int i &#061; 0; i System.out.println(arr[i]);
}
}

}



  1. 运行结果
    合并拍序

快速排序
对 int[] arr &#061; {10,7,2,4,7,62,3,4,2,1,8,9,19};这个无需的数组进行排序



  1. 经验归纳
    主要是理解合并排序和快速排序的算法思想&#xff0c;是对分治思想&#xff08;分解&#xff0c;求解&#xff0c;合并&#xff09;的应用。
    &#xff08;二&#xff09;题目二&#xff1a;棋盘覆盖



  2. 题目分析
    棋盘覆盖问题需要判断特殊方块所在的位置&#xff0c;每次都对分割后的四个小方块进行判断&#xff0c;判断特殊方格是否在里面。如果特殊方块在里面&#xff0c;这直接递归下去求即可&#xff0c;如果不在&#xff0c;这根据分割的四个方块的不同位置&#xff0c;把右下角、左下角、右上角或者左上角的方格标记为特殊方块&#xff0c;然后继续递归。



  3. 算法构造
    在此论证算法设计中的一些必要的设计依据。
    定义棋盘的大小&#xff1a;size&#061;(int)pow(2.0,(int)n);
    判断算法在哪个位置&#xff08;其中一个&#xff09;&#xff1a;if (dr {
    chessBoard(tr,tc,dr,dc,s);
    }
    else
    {
    chess[tr&#043;s-1][tc&#043;s-1] &#061; t;
    chessBoard(tr,tc,tr&#043;s-1,tc&#043;s-1,s);



  4. 算法实现
    程序源代码&#xff08;请写入必要的注释&#xff09;。
    package com.cn;
    import java.util.Scanner;
    public class CheckerBoard {

    static int Board[][]&#061;new int[50][50];
    static int L&#061;1;
    public static void checkerBoard(int zsh, int zsl, int dr, int dc, int size){
    // zsh:棋盘左上角方格的行号
    // zsl:棋盘左上角方格的列号
    // dr:标记块的行号
    // dc:标记块的列号
    if(size&#061;&#061;1){ //棋盘方格大小为,说明递归到最里层
    return;
    }
    int t&#061;L&#043;&#043;; //每次都加一&#xff0c;为了显示分治的次序
    int s&#061;size/2; //将棋盘进行
    if(dr checkerBoard(zsh, zsl, dr, dc, s);
    }
    else{ //用L型快覆盖右下角
    Board[zsh&#043;s-1][zsl&#043;s-1]&#061;t;
    checkerBoard(zsh, zsl, zsh&#043;s-1, zsl&#043;s-1, s);
    }
    if(dr&#061;zsl&#043;s){ //划分右下方的棋盘
    checkerBoard(zsh, zsl&#043;s, dr, dc, s);
    }
    else{ //用L型快覆盖右下角
    Board[zsh&#043;s-1][zsl&#043;s]&#061;t;
    checkerBoard(zsh, zsl&#043;s, zsh&#043;s-1, zsl&#043;s, s);
    }
    if(dr>&#061;zsh&#043;s && dc checkerBoard(zsh&#043;s, zsl, dr, dc, s);
    }
    else{ //用L型快覆盖右上角
    Board[zsh&#043;s][zsl&#043;s-1]&#061;t;
    checkerBoard(zsh&#043;s, zsl, zsh&#043;s, zsl&#043;s-1, s);
    }
    if(dr>&#061;zsh&#043;s && dc>&#061;zsl&#043;s){ //划分右下方的棋盘
    checkerBoard(zsh&#043;s, zsl&#043;s, dr, dc, s);
    }
    else{ //用L型快覆盖左上角
    Board[zsh&#043;s][zsl&#043;s]&#061;t;
    checkerBoard(zsh&#043;s, zsl&#043;s, zsh&#043;s, zsl&#043;s, s);
    }

    }
    public static void main(String[] args) {
    int n;
    int size;//棋盘大小
    System.out.println(“请输入棋盘规格数n(n行n列)”);
    Scanner scanner&#061;new Scanner(System.in);
    n&#061;scanner.nextInt();
    int x,y;
    size&#061;(int) Math.pow(2.0,n);
    System.out.println(“请输入标记点位于的行号&#xff1a;”);
    Scanner scanner1&#061;new Scanner(System.in);
    x&#061;scanner1.nextInt()-1;
    System.out.println(“输入标记点的列号&#xff1a;”);
    Scanner scanner2&#061;new Scanner(System.in);
    y&#061;scanner2.nextInt()-1;
    checkerBoard(0,0,x,y,size);
    for(int i&#061;0;i for(int j&#061;0;j System.out.println(Board[i][j]&#043;"-");
    }
    System.out.println();
    }
    }



}
4. 运行结果



  1. 经验归纳
    主要是分治思想&#xff0c;此问题的关键是要判断出特殊方块所在的位置&#xff0c;然后运用递归把所有情况都考虑一 遍就行了。

五、实验总结
这两个实验都用到了分治思想和递归思想。
第一题合并排序是将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff0c;即先使每个子序列有序&#xff0c;再使子序列段间有序。
快速排序是通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据都要小&#xff0c;然后再按此方法对这两部分数据分别进行快速排序&#xff0c;整个排序过程可以递归进行&#xff0c;以此达到整个数据变成有序序列。
第二题要分四种情况&#xff08;特殊方块可能在左上角、右上角、左下角、右下角&#xff09;讨论。

本文地址:https://blog.csdn.net/qq_45152962/article/details/109645643



推荐阅读
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了在Java中gt、gtgt、gtgtgt和lt之间的区别。通过解释符号的含义和使用例子,帮助读者理解这些符号在二进制表示和移位操作中的作用。同时,文章还提到了负数的补码表示和移位操作的限制。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
author-avatar
手机用户2502925313
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有