学号 2019-2020-1823 《数据结构与面向对象程序设计》实验六报告
班级: 1823
姓名: 杨凯涵
学号:20182321
实验教师:王志强
实验日期:2019年11月17日
必修/选修: 必修
1.实验内容
实验一
要求:定义一个Searching和Sorting类,并在类中实现linearSearch,SelectionSort方法,最后完成测试。
要求不少于10个测试用例,提交测试用例设计情况(正常,异常,边界,正序,逆序),用例数据中要包含自己学号的后四位
sorting类用的是选择排序,而searching类使用的是线性查找,这两个方法都是java算法里最最最最基本的算法了。代码如下
选择排序算法 public String selectionsort(String a) { String[] s = a.split("\\s"); int[] b = new int[s.length]; for(int i=0;i<b.length;i++) { int num = Integer.parseInt(s[i]); b[i]=num; } for(int i=0;i<b.length-1;i++) { for(int j=i+1;j<b.length;j++) { if(b[i]<b[j]) { int t = b[i]; b[i]=b[j]; b[j]=t; } } } String result=""; for(int i=0;i<b.length;i++) { result+=" "+b[i]; } return result; }
线性查找算法 public boolean linearSearch(String a, int target) { String[] s = a.split("\\s"); int data[]=new int[s.length]; for(int i=0;i<s.length;i++) { int num = Integer.parseInt(s[i]); data[i] = num; } for(int i = 0;i<data.length;i++) { if(data[i]==target) return true; } return false; }
选择排序和线性查找算法的核心就是一股劲的往前冲,基本上没有什么很特殊、很难的地方。
运行结果如下
而异常情况运行结果为
实验二
要求:重构你的代码
把Sorting.java Searching.java放入 cn.edu.besti.cs1823.(姓名首字母+四位学号) 包中(例如:cn.edu.besti.cs1823.G2301)
把测试代码放test包中
重新编译,运行代码,提交编译,运行的截图(IDEA,命令行两种)
首先在idea上运行,先把之前的两个类放入到题目要求的包中,然后再重新穿建立一个Test类,用来对其进行测试,测试代码如下
测试查找 public void testLinearSearch() { //正常 assertEquals(new shiyan7.Searching().linearSearch("21 25 48 76 53 54 89 87 56 77 63 65 42 1 3 5 7 9 8 6 4 2 23 21",54),true); assertEquals(new shiyan7.Searching().linearSearch("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 23 21",5),true); //异常 assertEquals(new shiyan7.Searching().linearSearch("12 3 5 48 7 98 78 62 6 45 87 6 3 548 6 98 63 45 78 6 23 21",28),false); assertEquals(new shiyan7.Searching().linearSearch("45 8 79 6 2 15 78 62 35 6 4 8 7 621 4 897 15 4564 23 21",34),false); //边界 assertEquals(new shiyan7.Searching().linearSearch("21 25 48 76 53 54 89 87 56 77 63 65 42 1 3 5 7 9 8 6 4 2 23 21",2),true); assertEquals(new shiyan7.Searching().linearSearch("21 25 48 76 53 54 89 87 56 77 63 65 42 1 3 5 7 9 8 6 4 2 23 21",21),true); //正序 assertEquals(new shiyan7.Searching().linearSearch("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2321",7),true); assertEquals(new shiyan7.Searching().linearSearch("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2321",19),true); //逆序 assertEquals(new shiyan7.Searching().linearSearch("23 21 10 9 8 7 6 5 4 3 2 1",23),true); assertEquals(new Searching().linearSearch("23 21 10 9 8 7 6 5 4 3 2 1",21),true); }
public void testSelectionsort() { //正常 assertEquals(new shiyan7.sort().selectionsort("1 4 7 2 5 8 3 6 9 10")," 10 9 8 7 6 5 4 3 2 1"); //逆序 assertEquals(new shiyan7.sort().selectionsort("1 2 3 4 5 6 7 8 9 10")," 10 9 8 7 6 5 4 3 2 1"); //正序 assertEquals(new sort().selectionsort("10 9 8 7 6 5 4 3 2 1")," 10 9 8 7 6 5 4 3 2 1"); }
然后我们的运行结果如下所示
在虚拟机中,我安装了junit
但是发现这个东西属实难用,和idea里面的简直就是一个天一个地,所以经过考虑,我决定使用驱动程序在虚拟机里面进行测试
实验三
要求:参考http://www.cnblogs.com/maybe2030/p/4715035.html ,学习各种查找算法并在Searching中补充查找算法并测试
我们按照里面的链接知道,编写相应的算法代码,并进行测试
二分查找
public int BinarySearch2(int a[], int value, int low, int high) { int mid = low+(high-low)/2; if(a[mid]==value) return mid; if(a[mid]>value) return BinarySearch2(a, value, low, mid-1); if(a[mid]<value) return BinarySearch2(a, value, mid+1, high); return 0; }
插入查找(其实和二分查找没什么区别)
public int InsertionSearch(int a[], int value, int low, int high) { int mid = low+(value-a[low])/(a[high]-a[low])*(high-low); if(a[mid]==value) return mid; if(a[mid]>value) return InsertionSearch(a, value, low, mid-1); if(a[mid]<value) return InsertionSearch(a, value, mid+1, high); return 0; }
斐波那契数列
public static boolean FibonacciSearch(int[] table, int keyWord) { //确定需要的斐波那契数 int i = 0; while (getFibonacci(i) - 1 == table.length) { i++; } //开始查找 int low = 0; int height = table.length - 1; while (low <= height) { int mid = low + getFibonacci(i - 1); if (table[mid] == keyWord) { return true; } else if (table[mid] > keyWord) { height = mid - 1; i--; } else if (table[mid] < keyWord) { low = mid + 1; i -= 2; } } return false; } //得到第n个斐波那契数 public static int getFibonacci(int n) { int res = 0; if (n == 0) { res = 0; } else if (n == 1) { res = 1; } else { int first = 0; int second = 1; for (int i = 2; i <= n; i++) { res = first + second; first = second; second = res; } } return res; }
哈希线性查找(需要先提前构造哈希函数)
public static boolean xianxing(Comparebale[] data , Comparebale target) { int num = target.geti()%9; boolean i ; while (data[num]!=null) { if(data[num].geti()==target.geti()) return true; else num++; } return false; }
这里我的哈希函数设置为h%9,大家可以自行设定
二叉树查找
public static boolean erchashu(Comparebale tree, Comparebale target) { while (tree!=null) { if(tree.geti()<target.geti()) { tree=tree.next; } else if (tree.geti()>target.geti()) { tree = tree.secondnext; } else if(tree.geti()==target.geti()) return true; } return false; }
二叉树之前也是要先构建
public class erchashu { Comparebale tree = new Comparebale(-1); Comparebale head = new Comparebale(-1); int[] a = new int[12]; public erchashu() { head.setNext(tree); } public void s(int[] b) { tree.setI(b[0]); for(int i=1;i<b.length;i++) { Comparebale c = new Comparebale(b[i]); tree = head.getNext(); while (tree.geti()!=b[i]) { if(tree.geti()<b[i]&&(tree.getNext()!=null)) { tree = tree.getNext(); } else if(tree.geti()<b[i]&&tree.getNext()==null) { tree.setNext(c); tree=c; } else if(tree.geti()>b[i]&&tree.getSecondnext()!=null) tree = tree.getSecondnext(); else if(tree.geti()>b[i]&&tree.getSecondnext()==null) { tree.setSecondnext(c); tree = c; } } } } public String toString( int[] a) { s(a); String result = ""; for(int i=0;i<a.length;i++) { result =result; } return result; } public Comparebale get() { return head.getNext(); } }
接着是分块查找
public static boolean blooksearch(int[] a ,int key) { int[] b = new int[3]; int n = a.length/3; int max = a[0]; int j=0; while (n<=9) { for(int i=n-3;i<n;i++) { if(max<a[i]) max = a[i]; } b[j]=max; j++; n=n+3; } for(int i=0;i<b.length;i++) { if(b[i]>=key) { for(int l = (i+1)*3-1;l>=(i+1)*3-3;l--) { if(a[l]==key) return true; } return false; } } return false; }
最后测试的运行截图为
实验四
要求:补充实现课上讲过的排序方法:希尔排序,堆排序,二叉树排序等(至少3个)
测试实现的算法(正常,异常,边界)
提交运行结果截图
希尔排序
public String sort (int[] arr) { for(int gap = arr.length/2;gap>0;gap/=2) { for(int i=gap;i<arr.length;i++) { int j =i; while (j-gap>=0&&arr[j]<arr[j-gap]) { int t = arr[j]; arr[j]=arr[j-gap]; arr[j-gap]=t; j-=gap; } } } String result = ""; for(int i=0;i<arr.length;i++) { result += " "+arr[i]; } return result; }
堆排序
public static void heapify(int[] arrays, int currentRootNode, int size) { if (currentRootNode < size) { //左子树和右字数的位置 int left = 2 * currentRootNode + 1; int right = 2 * currentRootNode + 2; //把当前父节点位置看成是最大的 int max = currentRootNode; if (left < size) { //如果比当前根元素要大,记录它的位置 if (arrays[max] < arrays[left]) { max = left; } } if (right < size) { //如果比当前根元素要大,记录它的位置 if (arrays[max] < arrays[right]) { max = right; } } //如果最大的不是根元素位置,那么就交换 if (max != currentRootNode) { int temp = arrays[max]; arrays[max] = arrays[currentRootNode]; arrays[currentRootNode] = temp; //继续比较,直到完成一次建堆 heapify(arrays, max, size); } } } public static void maxHeapify(int[] arrays, int size) { // 从数组的尾部开始,直到第一个元素(角标为0) for (int i = size - 1; i >= 0; i--) { heapify(arrays, i, size); } } public static String dui(int[] arrays) { for (int i = 0; i < arrays.length; i++) { //每次建堆就可以排除一个元素了 maxHeapify(arrays, arrays.length - i); //交换 int temp = arrays[0]; arrays[0] = arrays[(arrays.length - 1) - i]; arrays[(arrays.length - 1) - i] = temp; } String result=""; for(int i=0;i<arrays.length;i++) { result =result+ " "+arrays[i]; } return result; }
二叉树排序
public void s(int[] b) { tree.setI(b[0]); for(int i=1;i<b.length;i++) { Comparebale c = new Comparebale(b[i]); tree = head.getNext(); while (tree.geti()!=b[i]) { if(tree.geti()<b[i]&&(tree.getNext()!=null)) { tree = tree.getNext(); } else if(tree.geti()<b[i]&&tree.getNext()==null) { tree.setNext(c); tree=c; } else if(tree.geti()>b[i]&&tree.getSecondnext()!=null) tree = tree.getSecondnext(); else if(tree.geti()>b[i]&&tree.getSecondnext()==null) { tree.setSecondnext(c); tree = c; } } } }
代码测试运行截图为
异常截图
四(2)
实验五
要求:编写Android程序对实现各种查找与排序算法进行测试
提交运行结果截图
推送代码到码云
进行布局并放入代码进去之后,结果如图
1
2
3
4
5
6
7
8
9
10
3. 实验过程中遇到的问题和解决过程
问题一:如何进行堆排序算法?
问题一解决方法:了解堆排序之前就必须要知道一个完全二叉树的概念,何为完全二叉树,如下图
完全二叉树图
即除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐。它和满二叉树这个概念是一定要区分开的。从总体来讲,堆排序就是讲数据看成是完全二叉树类型,然后用二叉树的特性来进行排序的一种算法。
如下图
堆排序1
这是一个完全二叉树,而二叉树的数据其实都存储进了数组里面,左子树的序数其实是其父亲的2i+1,右子数的序数是其父亲的2i+2,可以按照这个特性将二叉树的值都依次附进数组里,接着我们发现左右子树都符合最大堆,但是父类子树不符合,则我们需要先对其父亲子树进行操作,让7在根节点上。
堆排序2
那这样右子数又不符合了,那我们又要对右子数进行调换,则
右子数变成了这样
堆排序3
这属于建堆成功,最后我们还需要进行调换,将最开头的元素与最末尾的元素进行调换,如下图
堆排序4
堆排序是通过不断的这样建堆的过程完成其排序的,详细我自己手写的下图
堆排序5
则这样我们就实现了堆排序,具体代码在我的实验过程里有了。
- 问题2:分块查找的算法是如何设计的?
- 问题2解决方法:分块查找其实是线性查找的改良版,它把一个线性集合的数组分成数个模块,每个模块有着的一个最大关键字作为索引
分块查找1
将所有的最大索引变成一个索引表,查找分为两部分,先对索引表进行二分查找或是顺序查找,以确定待查记录在哪一块中,然后,在已经确定的块中用顺序法进行查找。具体代码可看我的实验过程。
其他(感悟、思考等)
- 算法的排序查找是一个及其复杂的东西,让人掉发,关键在于设计算法出来后如何实现非常的困难,本人也只能上网去查阅他人资料学习。
只有在打下坚实的基础下,才能把这些排序算法打出来,否则会极易出现错误。
参考资料
《Java程序设计与数据结构教程(第二版)》
《Java程序设计与数据结构教程(第二版)》学习指导