实验一 算法设计基础

桂 林 理 工 大 学
实 验 报 告
同组实验者 无
实验名称 实验一 算法设计基础 日期 2020年 11 月13 日
一、实验目的:

掌握算法设计的基本步骤,并能进行时间复杂度分析。
掌握不同算法时间复杂度比较方法。

二、实验环境:

Eclipse

三、实验内容:

  1. 分别用穷举法和欧几里德算法实现求两个整数的最大公约数,并比较算法的效率。
    测试截图:
    在这里插入图片描述

  2. 排序算法效率比较。编程实现以下几种不同的排序算法(以升序为例):冒泡排序、选择排序、 希尔排序、快速排序,比较不同的排序过程的运行时间。具体要求:(1)为了消除数据之间差异导致排序效果的影响,使用相同的数组进行排序,方法为:首先创建一个数组,数组长度至少为100000,数组元素取值范围在[0, 100000]之间的随机正整数,并将这个数组复制4份,分别用不同的排序算法进行排序。(2)记录不同排序算法的运行时间。(3)对完全逆序的情况进行测试,将待排序数组赋值为逆序,即与最终排序要求完全相反。
    测试截图
    (2)
    在这里插入图片描述

(3)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201113195038820.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0MzY0MjY3,size_16,color_FFFFFF,t_70#pic_center

四、源代码:
第一题

import java.util.Scanner;

public class Main {
	public static int gcd(int a, int b)//欧几里得算法 
	{ 
		return b == 0 ? a : gcd(b, a % b);
	}
	public static int Exhaus(int a,int b) {//穷举法
	    int temp;  
		if(a < b) {
	        temp = a;
	        a = b;
	        b = temp;
	    }
	    for(temp = b;; temp--) {
	    	if(a%temp == 0&&b%temp == 0) break;
	    }
	    System.out.println("最大公约数为:"+temp);
	    return temp;
	}
    public static void main(String args[]){
    	Scanner input = new Scanner(System.in);
    	int a = input.nextInt();
    	int b = input.nextInt();
    	long start = 0;
		long end = 0;
		System.out.println("<--穷举法测试开始:-->");
    	start = System.currentTimeMillis();
    	System.out.println("最大公约数为:"+Exhaus(a,b));
    	end = System.currentTimeMillis();
    	System.out.println("穷举法耗时:"+(end - start) + "毫秒");
    	
    	System.out.println("<--欧几里得算法测试开始:-->");
    	start = System.currentTimeMillis();
    	System.out.println("最大公约数为:"+gcd(a,b%a));
    	end = System.currentTimeMillis();
    	System.out.println("欧几里得算法耗时:"+(end - start) + "毫秒");
    }
}

第二题

public class Solution {
	// --冒泡排序--
    public static void bubbleSort(int [] a, int N)
    {
       int j , k;
       int flag = N ;//flag来记录最后交换的位置,也就是排序的尾边界

       while (flag > 0){//排序未结束标志
        k = flag; //k 来记录遍历的尾边界
        flag = 0;

          for(j=1; j<k; j++){
            if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
                //交换a[j-1]和a[j]
                int temp;
                temp = a[j-1];
                a[j-1] = a[j];
                a[j]=temp;

                //表示交换过数据;
                flag = j;//记录最新的尾边界.
             }
          } 
      }
   }
	 
	// --希尔排序--
	//将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。
	//将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。
	static void shell_sort( int[] arr, int N )
	{
		int tmp;
		int  i;
		for (int d=N/2; d>0; d/=2)
		{
			for (int j=d; j<N; ++j)
			{
				tmp = arr[j];
				for (i=j; i>=d && arr[i-d]>tmp; i-=d)
					arr[i] = arr[i-d];
				arr[i] = tmp;
			}
		}
	}
	 
	// --选择排序--
	//选择排序:每次从待排序的元素中选出最小值  
	//算法性能分析:时间复杂度为O(N^2),对于长度为N的数组,需要进行N(N-1)/2次比较和0到N-1次交换。最好情况是已经有序,交换0次;最坏情况交换N-1次;逆序交换N/2次。
    public static void selectionSort(int[] arr ,int N){
        
        for(int i = 0; i < N - 1; i++){
            int min = i;
            for(int j = i + 1; j < N; j++){
                //将a[i]和a[i+1...N-1]中的最小元素交换
                if(arr[j] < arr[min]){//升序排列
                    min = j;
                }
            }
            if(min != i){
                int temp = arr[i];
                arr[i] = arr[min];
                arr[min] = temp;
            }
        }
    }
    //arr 需要排序的数组
    //low 开始时最左边的索引=0
    //high 开始时最右边的索引=arr.length-1
        public static void quickSort(int[] arr,int low,int high){
            int i,j,temp,t;
            if(low>high){
                return;
            }
            i=low;//左边哨兵的索引
            j=high;//右边哨兵的索引
            //temp就是基准位
            temp = arr[low];//以最左边为  基准位

            while (i<j) {
                //先看右边,依次往左递减
                //先从右往左找一个小于 基准位的数
                //当右边的哨兵位置所在的数>基准位的数 时
                //继续从右往左找(同时 j 索引-1)
                //找到后会跳出 while循环
                while (temp<=arr[j]&&i<j) {
                    j--;
                }

                //再看左边,依次往右递增
                //步骤和上面类似
                while (temp>=arr[i]&&i<j) {
                    i++;
                }

                //如果满足条件则交换
                if (i<j) {

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

                     //左右哨兵 交换数据(互相持有对方的数据)
                     arr[i] = y;
                     arr[j] = z;

                }

            }

    //这时 跳出了 “while (i<j) {}” 循环
    //说明 i=j 左右在同一位置
            //最后将基准为与i和j相等位置的数字交换
             arr[low] = arr[i];//或 arr[low] = arr[j];
             arr[i] = temp;//arr[j] = temp;


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

            //递归调用左半数组
            quickSort(arr, low, j-1);
            //递归调用右半数组
            quickSort(arr, j+1, high);
        }
    public static void main(String[] args) {

	   System.out.println("创建一个100000整数级随机数数组,分别进行排序,比较4种基本排序算法用时");
		
		long start = 0;
		long end = 0;
		
		int[] originArray = new int[100000];  //创建一个原始数组
		//填充随机数组
		for(int i = 0; i < originArray.length; i++) {
			originArray[i] = (int)(Math.random() * 100000);  //原始数组的每一个元素都是一个取之范围在[0, 99999]之间的随机整数
		}
		
		//为了公平起见,我们将原始数组拷贝4份,分别使用4种排序算法进行排序计算事件,消除因为随机数数组取之不同导致的差异
		int[] array1 = Arrays.copyOf(originArray, originArray.length);
		int[] array2 = Arrays.copyOf(originArray, originArray.length);
		int[] array3 = Arrays.copyOf(originArray, originArray.length);
		int[] array4 = Arrays.copyOf(originArray, originArray.length);
		int[] array5 = new int[1000];  //创建一个原始数组
		//逆序赋值
		for(int i = array5.length-1; i >= 0; i--) {
			array5[i] = i;  //原始数组的每一个元素都是一个取之范围在[0, 99999]之间的随机整数
		}
	
		//开始比较
		System.out.println("冒泡排序开始……");
		start = System.currentTimeMillis();
		bubbleSort(array1,array1.length);
		end = System.currentTimeMillis();
		System.out.println("冒泡排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		
		System.out.println("选择排序开始……");
		start = System.currentTimeMillis();
		selectionSort(array2,array2.length);;
		end = System.currentTimeMillis();
		System.out.println("选择排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		
		System.out.println("希尔排序开始……");
		start = System.currentTimeMillis();
		shell_sort( array3 , array3.length);
		end = System.currentTimeMillis();
		System.out.println("希尔排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		
		System.out.println("快速排序开始……");
		start = System.currentTimeMillis();
		quickSort(array4,0,array4.length-1);
		end = System.currentTimeMillis();
		System.out.println("快速排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		/*//第三题测试代码
		System.out.println("<--------对完全逆序的情况进行测试,将待排序数组赋值为逆序-------------->");
		start = System.currentTimeMillis();
		System.out.println("冒泡排序开始……");
		start = System.currentTimeMillis();
		bubbleSort(array5,array5.length);
		end = System.currentTimeMillis();
		System.out.println("冒泡排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		
		System.out.println("选择排序开始……");
		start = System.currentTimeMillis();
		selectionSort(array5,array5.length);;
		end = System.currentTimeMillis();
		System.out.println("选择排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		
		System.out.println("希尔排序开始……");
		start = System.currentTimeMillis();
		shell_sort( array5 , array5.length);
		end = System.currentTimeMillis();
		System.out.println("希尔排序结束,用时" + (end - start) + "毫秒");
		
		System.out.println("----------");
		
		System.out.println("快速排序开始……");
		start = System.currentTimeMillis();
		quickSort(array5,0,array5.length-1);
		end = System.currentTimeMillis();
		System.out.println("快速排序结束,用时" + (end - start) + "毫秒");*/
		
		System.out.println("----------");
		
   }
}

五、心得体会:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值