实验七

学号 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;
             }
         }


        }

    }

代码测试运行截图为

异常截图

实验五

要求:编写Android程序对实现各种查找与排序算法进行测试
提交运行结果截图
推送代码到码云

进行布局并放入代码进去之后,结果如图

3. 实验过程中遇到的问题和解决过程

问题一:如何进行堆排序算法?
问题一解决方法:了解堆排序之前就必须要知道一个完全二叉树的概念,何为完全二叉树,如下图

即除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐。它和满二叉树这个概念是一定要区分开的。从总体来讲,堆排序就是讲数据看成是完全二叉树类型,然后用二叉树的特性来进行排序的一种算法。

如下图

这是一个完全二叉树,而二叉树的数据其实都存储进了数组里面,左子树的序数其实是其父亲的2i+1,右子数的序数是其父亲的2i+2,可以按照这个特性将二叉树的值都依次附进数组里,接着我们发现左右子树都符合最大堆,但是父类子树不符合,则我们需要先对其父亲子树进行操作,让7在根节点上。

那这样右子数又不符合了,那我们又要对右子数进行调换,则

右子数变成了这样

这属于建堆成功,最后我们还需要进行调换,将最开头的元素与最末尾的元素进行调换,如下图

堆排序是通过不断的这样建堆的过程完成其排序的,详细我自己手写的下图

则这样我们就实现了堆排序,具体代码在我的实验过程里有了。

  • 问题2:分块查找的算法是如何设计的?
  • 问题2解决方法:分块查找其实是线性查找的改良版,它把一个线性集合的数组分成数个模块,每个模块有着的一个最大关键字作为索引

将所有的最大索引变成一个索引表,查找分为两部分,先对索引表进行二分查找或是顺序查找,以确定待查记录在哪一块中,然后,在已经确定的块中用顺序法进行查找。具体代码可看我的实验过程。

其他(感悟、思考等)

  • 算法的排序查找是一个及其复杂的东西,让人掉发,关键在于设计算法出来后如何实现非常的困难,本人也只能上网去查阅他人资料学习。
  • 只有在打下坚实的基础下,才能把这些排序算法打出来,否则会极易出现错误。

参考资料

《Java程序设计与数据结构教程(第二版)》

《Java程序设计与数据结构教程(第二版)》学习指导

posted @ 2019-11-17 15:42  楊某人  阅读(170)  评论(0编辑  收藏  举报