实验三 查找和排序 实验报告 20162305

实验三 查找和排序 实验报告 20162305

一、查找和排序-1

1、实验要求
  • 完成教材P302 Searching.Java ,P305 Sorting.java中方法的测试
    不少于10个测试用例,提交测试用例设计情况(正常,异常,边界,正序,逆序),用例数据中要包含自己学号的后四位
    提交运行结果图(可多张)
2、实验过程
  • 这个实验是在教材上的代码基础上实现的。教材中给了Searching类和Sorting类,测试这两个代码中给出的方法。查找类中包含了线性查找和二分查找两种方法。排序类中包含了像选择排序,插入排序,冒泡排序等等方法。这些方法在之前的学习中已经了解过,设计测试类,在两个类的测试类中一一实现这些方法。
3、实验成果截图

1062726-20171111100213591-165585508.png

1062726-20171111100220763-1799850320.png

二、查找和排序-2

1、实验要求
  • 重构你的代码
    把Sorting.java Searching.java放入 cn.edu.besti.cs1623.(姓名首字母+四位学号) 包中
    把测试代码放test包中
    重新编译,运行代码,提交编译,运行的截图(IDEA,命令行两种)
2、实验过程
  • 按照实验要求,我在IDEA中新建了一个package包,命名为cn.edu.besti.cs162305.lyx。在IDEA中重构代码,将代码加入相应的文件夹中,然后运行,在IDEA中可以实现。不过打开命令行后编译成功后,命令行中显示代码编译没问题,不过结果却没能显示出来。
3、实验成果截图
  • 命令行
    1062726-20171111103459888-606107507.png

  • IDEA
  • 1、
    1062726-20171111103516356-550129968.png
  • 2、
    1062726-20171111103529403-1784961581.png

三、查找和排序-3

1、实验要求
  • 参考 查找算法博客 在Searching中补充查找算法并测试
    提交运行结果截图
2、实验过程
  • 在这篇学习博客中,一共提到了7种查找的方法,分别是顺序查找、二分查找、插值查找、斐波那契查找、树表查找、分块查找和哈希查找。其中的顺序查找和二分查找在教材的代码中都已经实现,下面介绍其他五种查找方法
(1)、插值查找
  • 插值查找是基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。
  • 插值查找在实际使用时,一般要满足两个假设条件:
    (1)每一次对数据的访问与通常的指令相比,费用都是相当昂贵的。例如,待查找的表一定是在磁盘而非内存中,因而每一次比较都
    要进行磁盘访问。
    (2)数据不仅是已被排好序的,而且呈现均匀分布特征。

  • 实验代码


public static Comparable InsertionSearch(int[] num, int key) {
        //定义三个判断数
        int low, high, mid;
        low = 0;
        high = num.length - 1;
        while (low <= high) {
            // mid = (low + high) / 2;
            //二分查找
            mid = low + (high - low) * (key - num[low]) / (num[high] - num[low]); // 插值查找
            if (key < num[mid]) high = mid - 1;
            else if (key > num[mid]) low = mid + 1;
            else
                // 如果等于则直接还回下标值
                return mid;
        }
        return -1;
    }
(2)、斐波那契查找
  • 斐波那契查找也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。
      
  • 相对于折半查找,一般将待比较的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;
    3、high=mid-1,k-=1。

  • 说明: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个,所以可以递归的应用斐波那契查找。

  • 实验代码


 private int max_size = 20;//斐波那契数组的长度

    /*构造一个斐波那契数组*/
    public void Fibonacci(int[] F) {
        F[0] = 0;
        F[1] = 1;
        for (int i = 2; i < max_size; ++i)
            F[i] = F[i - 1] + F[i - 2];
    }

    /*定义斐波那契查找法*/
    int FibonacciSearch(int[] a, int key)  //a为要查找的数组,n为要查找的数组长度,key为要查找的关键字
    {
        int low = 0;
        int high = a.length - 1;

        int[] F = new int[max_size];
        Fibonacci(F);//构造一个斐波那契数组F

        int k = 0;
        while (a.length > F[k] - 1)//计算n位于斐波那契数列的位置
            ++k;
        //将数组a扩展到F[k]-1的长度

        int[] temp = new int[F[k] - 1];
        
        for (int i = 0; i < a.length; i++)
            temp[i] = a[i];


        for (int i = a.length; i < F[k] - 1; ++i)
            temp[i] = a[a.length - 1];

        while (low <= high) {
            int mid = low + F[k - 1] - 1;
            if (key < temp[mid]) {
                high = mid - 1;
                k -= 1;
            } else if (key > temp[mid]) {
                low = mid + 1;
                k -= 2;
            } else {
                if (mid < a.length) return mid; //若相等则说明mid即为查找到的位置
                else return a.length - 1; //若mid>=n则说明是扩展的数值,返回n-1
            }
        }

        return 0;
    }
(3)、二叉树查找
  • 实现这个方法相对简单。我们可以利用之前实现过的二叉查找树来实现查找功能。定义一个二叉查找树,遍历整个数,利用二叉查找树中的find方法来查找目标值,从而实现查找功能。
  • 实验代码

 public int BinaryTreeSearch(int[] a, int key) {
        LinkedBinarySearchTree linkedBinarySearchTree = new LinkedBinarySearchTree();
        //添加元素进入查找树
        for (int i = 0; i < a.length; i++)
            linkedBinarySearchTree.add(a[i]);
        //利用find方法查找值
        if (linkedBinarySearchTree.find(key) == null) return Integer.parseInt(null);
        else return key;

    }
(4)、分块查找
  • 分块查找又称索引顺序查找,它是顺序查找的一种改进方法。将n个数据元素"按块有序"划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须"按块有序";即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,以此类推。

  • 实验代码


public static int blockSearch(int[] index, int[] a, int key, int m) {  
    // 在序列a数组中,用分块查找方法查找关键字为key的记录  
    // 1.在index[ ] 中折半查找,确定要查找的key属于哪个块中  
    int i = binarySearch(index, key);  
    if (i >= 0) {  
        int j = i > 0 ? i * m : i;  
        int length = (i + 1) * m;  
        // 在确定的块中用顺序查找方法查找key  
        for (int k = j; k < length; k++) {  
            if (key == a[k]) {  
                System.out.println("查询成功");  
                return k;  
            }  
        }  
    }  
  
    return -1;  
}  
(5)、哈希查找 
  • 利用Java中的HashMap类实现查找功能。其实现过程和二叉查找树实现查找类似。利用HashMap中的put方法将元素添加入表中,再用containKey方法判断有无目标元素,从而实现查找功能。
  • 实验代码

    public int HashSearch(int[] a , int key){
        HashMap<Integer,Integer> hashMap = new HashMap();
        for(int i = 0;i <a.length;i++)
            hashMap.put(i,a[i]);
        if(hashMap.containsKey(key) == true)
            return key;
        else
            return 0;
    }
3、实验成果截图

1062726-20171111131027309-1904315712.png

四、查找和排序-4

1、实验要求
  • 补充实现课上讲过的排序方法:希尔排序,堆排序,桶排序,二叉树排序等。测试实现的算法(正常,异常,边界),提交运行结果截图,推送相关代码到码云上
2、实验过程
(1)、希尔排序
  • 希尔排序的思想是先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
  • 实验代码

 public static void shellSort(int[] data) {
        int j = 0;
        int temp = 0;
        for (int a = data.length / 2; a > 0; a /= 2) {
            for (int i = a; i < data.length; i++) {
                temp = data[i];
                for (j = i - a; j >= 0; j -= a) {
                    if (temp < data[j]) {
                        data[j + a] = data[j];
                    } else {
                        break;
                    }
                }
                data[j + a] = temp;
            }
            for (int i = 0; i < data.length; i++)
                System.out.print(data[i] + " ");
        }
    }
(2)、堆排序
  • 利用之前完成的LinkedMaxHeap实现排序功能。根据最大堆的性质依次返回值并打印出来,实现排序功能
  • 实验代码

 public void heapSort(Comparable[] data){
        LinkedMaxHeap linkedMaxHeap = new LinkedMaxHeap();
        for (int i = 0; i < data.length; i++)
            linkedMaxHeap.add(data[i]);
        for (int i = data.length-1; i>=0;i--)
            data[i]=linkedMaxHeap.removeMax();
    }

(3)、桶排序
  • 桶排序的基本思想是将一个数据表分割成许多buckets,然后每个bucket各自排序,或用不同的排序算法,或者递归的使用bucket sort算法。基本流程是先建立一堆buckets,再遍历原始数组,并将数据放入到各自的buckets当中,对非空的buckets进行排序; 按照顺序遍历这些buckets并放回到原始数组中即可构成排序后的数组。

  • 实验代码


 public static void bucketSort(int[] arr){

        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for(int i = 0; i < arr.length; i++){
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }

        //桶数
        int bucketNum = (max - min) / arr.length + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
        for(int i = 0; i < bucketNum; i++){
            bucketArr.add(new ArrayList<Integer>());
        }

        //将每个元素放入桶
        for(int i = 0; i < arr.length; i++){
            int num = (arr[i] - min) / (arr.length);
            bucketArr.get(num).add(arr[i]);
        }

        //对每个桶进行排序
        for(int i = 0; i < bucketArr.size(); i++){
            Collections.sort(bucketArr.get(i));
        }


    }

(4)、二叉树排序
  • 利用二叉查找树的性质实现排序功能,利用类中findMin()方法将数组中的元素排序。
  • 实验代码

public static void BinaryTreeSort(Comparable[] a){
        LinkedBinarySearchTree linkedBinaryTree = new LinkedBinarySearchTree();
        for (int i = 0; i < a.length; i++)
            linkedBinaryTree.add(a[i]);
        for (int i = 0; i < a.length; i++) {
            a[i] = linkedBinaryTree.findMin();
            linkedBinaryTree.remove(linkedBinaryTree.findMin());
        }
    }
3、实验成果截图

1062726-20171111133900591-718236698.png

转载于:https://www.cnblogs.com/lyxwatm/p/7822400.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.实验目的 掌握内排序,比较各种排序的优、缺点。 2 需求分析 2.1原理 2.1.1、直接排序 算法描述:经过i-1遍处理后,L[1..i-1]己排好序。第i遍处理仅将L[i]插入L[1..i-1]的适当位置,使得L[1..i]又是排好序的序列。要达到这个目的,我们可以用顺序比较的方法。首先比较L[i]和L[i-1],如果L[i-1]≤ L[i],则L[1..i]已排好序,第i遍处理就结束了;否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个位置j(1≤j≤i-1),使得L[j] ≤L[j+1]时为止。 2.1.2、冒泡排序 算法描述:核心思想是扫描数据清单,寻找出现乱序的两个相邻的项目。当找到这两个项目后,交换项目的位置然后继续扫描。重复上面的操作直到所有的项目都按顺序排好。 2.1.3、快速排序 算法描述:首先检查数据列表中的数据数,如果小于两个,则直接退出程序。如果有超过两个以上的数据,就选择一个分割点将数据分成两个部分,小于分割点的数据放在一组,其余的放在另一组,然后分别对两组数据排序。通常分割点的数据是随机选取的。这样无论你的数据是否已被排列过,你所分割成的两个字列表的大小是差不多的。而只要两个子列表的大小差不多。 2.1.4、选择排序 算法描述:首先找到数据清单中的最小的数据,然后将这个数据同第一个数据交换位置;接下来找第二小的数据,再将其同第二个数据交换位置,以此类推。 2.1.5、堆排序 (1) 基本思想:堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。 (2) 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性: Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2]) 2.1.6、希尔排序 算法描述:在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,并且对插入下一个数没有提供任何帮助。如果比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。 2.2要求 1.本程序对以下六种常用内部排序算法进行实测比较:冒泡排序,插入排序,选择排序,希尔排序,快速排序,堆排序。 2.排序的元素的关键字为整数。用正序,逆序,不同乱序的数据作测试比较。比较的指标为有关键字参加的比较次数和关键字的移动次数。 3.程序以人机对话的形式进行,每次测试完毕显示各种比较指标值 。 2.3任务 设计一个测试程序比较几种内部排序算法的关键字比较次数和移动次数以取得直观感受。 2.4运行环境 (1)WINDOWSXP系统 (2)C++ 编译环境 3.实验方法 本实验主要是内排序,通过比较的次数和移动的次数判断排序的好坏。主要子函数的说明如下。 1.简单选择排序XuanzePaixu(); 2.冒泡排序MaopaoPaixu(); 3. 直接插入排序CharuPaixu(); 4. 快速排序KuaisuPaixu(); 5. 堆排序DuiPaixu(); 6. 希尔排序 XierPaixu(); 以上的排序算法均采用书中所用的算法。程序采用输入的时候仅输入所要的个数,具体的输入数据由程序随机产生个数,并且输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值