20172304 实验三报告

20172304 实验二报告

  • 课程:《软件结构与数据结构》
  • 班级: 1723
  • 姓名: 段志轩
  • 学号:20172304
  • 实验教师:王志强
  • 助教:张师瑜&张之睿
  • 实验日期:2018年11月5日-2018年11月12日
  • 必修选修: 必修php

    实验要求

    实验三-查找与排序-1
    定义一个Searching和Sorting类,并在类中实现linearSearch(教材P162 ),SelectionSort方法(P169),最后完成测试。要求很多于10个测试用例,提交测试用例设计状况(正常,异常,边界,正序,逆序),用例数据中要包含本身学号的后四位提交运行结果图。
    实验三-查找与排序-2
    重构你的代码
    把Sorting.java Searching.java放入 cn.edu.besti.cs1723.(姓名首字母+四位学号) 包中(例如:cn.edu.besti.cs1723.G2301)把测试代码放test包中从新编译,运行代码,提交编译,运行的截图(IDEA,命令行两种)html

实验三-查找与排序-3
参考http://www.cnblogs.com/maybe2030/p/4715035.html 在Searching中补充查找算法并测试提交运行结果截图
实验三-查找与排序-4
补充实现课上讲过的排序方法:希尔排序,堆排序,二叉树排序等(至少3个)
测试实现的算法(正常,异常,边界)
提交运行结果截图
实验三-查找与排序-5(选作,加分)
编写Android程序对各类查找与排序算法进行测试
提交运行结果截图java

实验过程及实验结果

实验一过程及结果:
本次实验主要内容是对以前已经学习过的顺序查找和选择排序进行测试,实际上就是让咱们再次熟悉一下junit测试的相关内容以及复习一下有关顺序查找和选择排序的相关内容。可是因为后续实验的内容都是在Sorting类以及Searching类的基础上继续改进的,因此在此我就不讲相关的码云连接给出,而只给出顺序查找以及选择排序的相关代码。
顺序查找android

public static <T> boolean linearSearch(T[] data, int min, int max, T target) {
        int index = min;
        boolean found = false;

        while (!found && index <= max) {
            found = data[index].equals(target);
            index++;
        }

        return found;
    }

选择排序git

public static <T extends Comparable<T>> T[] selectionSort(T[] data)
    {
        int min;
        T temp;

        for (int index = 0; index < data.length-1; index++)
        {
            min = index;
            for (int scan = index+1; scan < data.length; scan++)
                if (data[scan].compareTo(data[min])<0)
                    min = scan;

            swap(data, min, index);
        }
        return data;
        }
private static <T extends Comparable<? super T>> void swap(T[] data, int index1, int index2)
        {
            T temp = data[index1];
            data[index1] = data[index2];
            data[index2] = temp;
        }

而后将相关的junit测试截图发过来
这是顺序查找的图片
web


这是选择排序的图片

说明:因为要求至少十个测试用例,因此我将两个方法的测试的每种状况(正常,异常,边界,正序,逆序)在查找的测试中,虽然我不知道测试边界究竟有什么用,可是我仍是查找了两个位于给定数组边界的两个元素,在设置异常的时候,考虑到实现的顺序查找的是须要给定的查找范围的,因而就给定了一个超过给定数组范围的范围,而且为他大度划分出了一个测试的空间,最后不出意外的出现了异常,抛出了ArrayIndexOutOfBoundsException,也就是咱们认知意义上的数组越界异常。
在处理选择排序的时候,虽然仍是不理解测试一个正序数组道德排序究竟有何意义,可是仍是作了,而且为了知足10个用例的要求,最终也是每一个状况作了多组数据的测试,可是考虑到排序算法彷佛并无所谓的什么边界,因此最终就没有作这方面的测试,在进行设置异常的时候。首先声明了一个Comparable数组,这个数组有个很神奇的地方就是它可以同时容纳不一样类型的数据,因此我就在这个数组中储存了整数型的数据和文本型也就是String类型的数据。而后在进行排序的时候理所固然的就会出现异常。最终抛出的异常是ClassCastException: java.lang.Integer cannot be cast to java.lang.String,也就是类型转换异常:整数型变量不能转换为文本型变量。算法

实验二过程与结果
重构你的代码
把Sorting.java Searching.java放入 cn.edu.besti.cs1723.(姓名首字母+四位学号) 包中(例如:cn.edu.besti.cs1723.G2301)把测试代码放test包中从新编译,运行代码,提交编译,运行的截图(IDEA,命令行两种)
实验二的idea部分实际上并无什么难度,只是换了一个位置,而后从新进行测试就是了。最后的结果和实验一雷同,因而就不在此放出图片了。而后就是命令行部分的实现了,出于严谨的态度,我请示了一下王老师,命令行模式是否也要在junit中进行测试,在获得确定回答后就是噩梦的开始。首先上网上查资料。查到了首先应该是导入一个插件,也就是所谓的后缀为.jar的东西,下载以后就是导入的过程了。首先是找到导入位置,多是过久没有人有勇气尝试在命令行中进行junit测试了,网上给定的教程的版本不知落后了个人虚拟机版本不知道多少辈子子孙孙。终于在费尽九牛二虎之力后,终于找到疑似目标以后,却又被权限困住了。还曾记得老师曾经教过咱们,咱们所学的是面向对象的设计是顶层设计,可是没想到本身最后却败在底层结构上了。图形界面没权限,命令行通常的移动命令mv彷佛也不能识.jar这个东西。系统给个人提示是系统并不认为这是个文件,当时我就崩了,心里中犹如滔滔江水,泛滥而过,一发不可收拾。最终在挣扎与无奈中,伴随着12点钟声的响起,只能与个人实验二的另外一半分数道别。别了,实验二的另外一半。曾经有一份分数摆在我面前,我没有珍惜,若是上天能再给我一次机会,我会对他说:“junit仍是idea的好。”
实验三过程与结果
决策树,这个的实现是基于书上的代码,这个实际上也没有也没有太大的难度
DecisionTree码云连接
CharacterAnalyzer
这是我设计的决策树

测试结果
shell

实验三
这个实验主要就是要求咱们阅读老师给定的博客,而后将相关算法补充完整,实际上,这更加相似于,将C++翻译成java的过程。除了实验一中已经使用过的顺序查找,这篇博客中还给出了二分查找,插值查找,斐波那契查找,平衡查找树,分块查找,哈希查找。处于治学严谨的态度,首先我要介绍着几种算法的原理。。
首先是顺序查找。
顺序查找顾名思义,就是按照顺序查找,就是从头开始依次向下进行。
而后二分查找是创建在已经排序好的数组的基础上的。首先由首尾两个数据算出将要做为标准的中间值,而后将查找目标与中间值进行比较。若是相等就返回true。若是小于中间值。则取中间值左面的数组,若是大于则反之。最后若是找到元素返回true,不然返回false。
下面是有关两个查找算法的动图

而后是插值查找,
其实插值查找时相似于二分查找的下面的公式中的第一行就是二分查找的公式,第二行是插值查找的公式。其中mid就是每次所肯定的要与目标进行比较的值。而low和high就是每次从新划分完区域以后从新肯定的最大值和最小值。能够看出插值查找经过改进算法,使得改进后的算法在面对分布较为均匀的数据时,有较好的效率。
mid=(low+high)/2, 即mid=low+1/2(high-low);
mid=low+(key-a[low])/(a[high]-a[low])
(high-low),
插值查找示意图

而后是斐波那契查找
相对于折半查找,通常将待比较的key值与第mid=(low+high)/2位置的元素比较,比较结果分三种状况:
1)相等,mid位置的元素即为所求
2)>,low=mid+1;
3)<,high=mid-1。 斐波那契查找与折半查找很类似,他是根据斐波那契序列的特色对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;
开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种
1)相等,mid位置的元素即为所求
2)>,low=mid+1,k-=2;
说明:low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,因此能够递归的应用斐波那契查找。
3)<,high=mid-1,k-=1。
说明:low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1个,因此能够递归 的应用斐波那契查找。
斐波那契查找动态图

平衡查找树
这个实际上就是利用构建好的平衡查找树的性质来进行查找元素。平衡查找树构建要求右子树大于左子树。左子树小于右子树。且左右两子树高度差绝对值不超过一。
平衡查找树动态图展现。

分块查找
要求将数据分红块,而且前一块的任一元素都不能大于后面块中的元素。因此这个算法应该是创建在数据已经排好序的的基础上道德。而后将每一块的最大元素取出而后创建一个索引列表。在将目标元素与索引列表中的元素进行比较,最后找到目标元素所在的分块,最后再次使用顺序或者二分查找进行查找,而后根据查找结果分别返回true或false。
分块查找图片展现

哈希查找
首先得将代查数据按照哈希规则存入哈希表中。所谓哈希规则就是将数据经过某种函数,来肯定他在表中的位置。例如数据b=a%11,其中a表示数据,b表示数据在表中的位置,可是有时数据之间会产生冲突。例如。1%11=1,12%11=1,这时两个不一样的数据却经过函数产生了相同的地址,这就是所谓的冲突。解决哈希冲突的办法有不少,可是其中最经常使用的就是链地址法。就是在数组中储存的并非一个个具体的数据,而是链表,一旦发生冲突,就将数据插入到链表的末尾。在查找的时候也是遵循一样的规则的,首先将待查元素经过函数求得其目标位置,而后,在遍历链表,若是找到就返回true,若是没有找到就返回false。
实现代码。因为代码太多因此就将其置于下面连接之中。
Searching
测试类代码数组

package cn.edu.besti.cs1723.DZX2304;



public class Searchingtest {
    public static void main(String[] args) {
    Integer[] a={10,2,8,19,16,18,20,51,};//被查找的数组
       Integer []a1={2,8,10,16,18,19,20,51};
        Searching b=new Searching();


        System.out.println("线性查找查找50的结果:" + Searching.linearSearch(a,0,7,50));
        System.out.println("线性查找查找2的结果:"+Searching.linearSearch(a,0,7,2));
        System.out.println("二分查找50的结果:" + b.BinarySearch1(a1,50,7));
        System.out.println("二分查找2的结果:" + b.BinarySearch1(a1,2,7));
       System.out.println("插值查找可否找到50:" + b.InterpolationSearch(a1, 50));
        System.out.println("插值查找可否找到2:" + b.InterpolationSearch(a1,2));
        System.out.println("斐波那契查找可否找到50:" + Searching.FibonacciSearch(a1,0,11, 50));
        System.out.println("斐波那契查找可否找到2:" + Searching.FibonacciSearch(a1,0,11, 2));
        System.out.println("二叉查找树查找可否找到50:" + b.BinarySearchTreeSearch(a,0,7,50));
        System.out.println("二叉查找树查找可否找到2:" + b.BinarySearchTreeSearch(a,0,7,2));
        System.out.println("分块查找可否找到50:" + Searching.partitionSearch(a,0,7,50));
        System.out.println("分块查找可否找到2:" + Searching.partitionSearch(a,0,7,2));
        System.out.println("哈希表查找50的结果" +b.Hashsearching(a,50));
        System.out.println("哈希表查找2的结果"+b.Hashsearching(a,2));
    }}

测试结果截图
数据结构

实验四
这个实验主要是补充老师曾经讲过的排序算法,什么希尔排序堆排序以及二叉树排序,本身也能够实现排序算法。除了这两个排序算法以外,我还实现了插入排序和快速排序。
首先向你们介绍一下这几种算法。
首先是希尔排序,希尔排序的具体算法应用就是首先肯定一个步长,从第一个元素开始,比较间隔步长-1个元素的元素,若是不符合与其的排序规则就交换两个元素。而后逐渐减小步长直至最后步长小于1为之。
希尔排序动态示意图

堆排序讲解
堆排序是一种比较复杂的排序,它是在二叉平衡树的基础上实现的。对分为两种,一种是大顶堆,大顶堆的全部子树的父结点都不小于其孩子结点。而小顶堆的全部子树的父结点都不大于他的孩子结点。我就简单介绍一下使用对进行排序的部分,而具体生成堆的部分我就再也不赘言了。主要说一下使用堆进行排序的部分。以大顶堆为例。因为大顶堆的性质,致使最大的元素就是根节点,因而将根节点取出,而后将第一个非叶子结点取出,置为根节点。而后再次生成堆。依此类推。
堆排序动态展现

二叉树排序讲解
实际上二叉树排序实际上就是生成二叉查找树而后经过中序遍历就会获得排好序的数据。
二叉查找树生成动态示意图

插入排序讲解
实际上插入排序就是从头开始遍历,将未排序的元素与已排序的元素逐个进行比较而后,直接将其插入到适合的位置。

插入排序示意图

快速排序
从数列中挑出一个元素,称为 “基准”(pivot);
从新排序数列,全部元素比基准值小的摆放在基准前面,全部元素比基准值大的摆在基准的后面(相同的数能够到任一边)。在这个分区退出以后,该基准就处于数列的中间位置。这个称为分区(partition)操做;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
快速排序动态展现

实现代码。因为代码太多因此就将其置于下面连接之中。
Sorting.java
测试类代码

package cn.edu.besti.cs1723.DZX2304;

public class SortingTest {
    public static void main(String[] args) {
        Comparable a[] = {10, 25, 2304,  44, 56, 11, 9, 8};
        Sorting b = new Sorting();
       Sorting.selectionSort(a);
        System.out.println("选择排序后的数组");
        for(Comparable c:a)
        {
            System.out.print(c+" ");
        }
        System.out.println();
        Comparable a2[]= {10, 25, 2304,  44, 56, 11, 9, 8};
         Sorting.insertionSort(a2);
        System.out.println("插入排序后的数组");
        for(Comparable c:a2)
        {
            System.out.print(c+" ");
        }
        System.out.println();
        Comparable a3[]= {10, 25, 2304,  44, 56, 11, 9, 8};
        Sorting.quickSort(a3);
        System.out.println("快速排序后的数组");
        for(Comparable c:a3)
        {
            System.out.print(c+" ");
        }
        System.out.println();
        Comparable a4[]= {10, 25, 2304,  44, 56, 11, 9, 8};
        Sorting.shellSort(a4);
        System.out.println("希尔排序后的数组");
        for(Comparable c:a4)
        {
            System.out.print(c+" ");
        }
        System.out.println();
        Comparable a5[]= {10, 25, 2304,  44, 56, 11, 9, 8};
        Sorting.heapSort(a5);
        System.out.println("堆排序后的数组");
        for(Comparable c:a5)
        {
            System.out.print(c+" ");
        }
        System.out.println();
        Comparable a6[]= {10, 25, 2304,  44, 56, 11, 9, 8};
        Sorting.binarySearchTreeSort(a6);
        System.out.println("二叉查找树排序后的数组");
        for(Comparable c:a6)
        {
            System.out.print(c+" ");
        }
        Comparable[] a7={10, "a", 2304,  44, "b", 11, 9, 8};
        Sorting.binarySearchTreeSort(a7);
        System.out.println("二叉查找树排序后的数组");
        for(Comparable c:a7)
        {
            System.out.print(c+" ");
        }
    }
}

测试结果截图

这里我放置了一组异常对照。
实验五
实验五是真的没什么好说的了,就是将代码在android上实现

代码调试时碰见的问题

问题:为何斐波那契查找的结果和预期结果不一致
解决方案:后来发现是在进行斐波那契查找时没有使用已经排序好的数组。

其余

此次实验又是一次复习实验,通过屡次的磨练相信咱们对各类短发的理解会更加深刻,对各类代码的运用会更加熟练。咱们会不断地成长进步直至本身能开拓出一片属于本身的天空。

参考资料

1.蓝墨云班课
2.java软件结构与数据结构

相关文章
相关标签/搜索