排序算法

题目描述:

实验总体思路:

利用switch结构来选择实验所要用的排序算法,每一种排序都用相同的计算运行时间的代码,不同的算法就在算法实现部分进行改动(如下代码1至5所示)。不断的改变数据规模,每一个规模在实验时,用循环进行多次实验并作为样本记录消耗的时间。最后输出在不同排序算法下,不同的数据规模的20次实验样本和平均用时

1、选择排序

代码1:

for i=0 to n-2

min=i

for j= i+1 to n-1

if ele[min]>ele[j]  min=j

swap(ele[i],ele[min])  //交换

 

             图1、选择排序在不同数据规模下排序所消耗的时间

2、冒泡排序

代码2

for i= 0 to n-1

for j=0 to n-1-i

if a[j]>a[j+1]

swap(a[j],a[j+1])  //交换

 

图2、冒泡排序在不同数据规模下排序所消耗的时间

 

3、合并排序

代码3

Merge(ele[1...n],left,right)

middle=(left+right)/2

if right>1eft+1

       Merge(ele,left,middle)

      Merge(ele,middle+1,right)

l←left r←right i←left

while l<=middle&&r<=right  //两组分别一一比较,数据小的放入ele

      if ele[l]<=ele[r]

             t[i++]←ele[l++]

      else

             t[i++]←ele[r++]

while l>middle&&r<=r   //只剩一组还有剩余的时,将剩下的按顺序放入

    ele[i++]=s[r++]

while l<=middle && r>right

    ele[i++]=s[l++];

        

图3、合并排序在不同数据规模下排序所消耗的时间

 

 

4、快速排序

代码4

quick(ele[0...n-1],left,right)

if l<r

l←left  r←right  x←ele[l];

while l<r

             while l<r && x<=ele[r]  //找到一个比x小的数之后交换到前面的部分

r--

             if l<r 

ele[l]←ele[r]  l++

while l<r && x>ele[l]  //与上面相反

ll++

              if l<r

                    ele[r]←ele[l]  r--

      ele[l]←x;

      quick(ele,left,l-1) // 递归调用

      quick(ele,l+1,right)

图4、快速排序在不同数据规模下排序所消耗的时间

 

5、插入排序

代码5

for i=1→n-1

      if ele[i]<ele[i-1]  temp=ele[i]

for j= i-1 to 0 && ele[j]>temp

                    ele[j+1]←ele[j]

             ele[j+1]←temp

 

具体实现:

package jj;

import java.util.Arrays;
import java.util.Date;
import java.util.Scanner;
/**
 * 2018/12/1
 * @author jjw
 *
 */
public class Paixu {
	public static void swap(int a,int b){
		int t=a;
		a=b;
		b=t;
	}
	//快速排序
	//平均效率O,适用于排序大列表
	public static void quick(int[] Data,int left,int right) 
    {  
      int i,j; //下标
      int middle,temp; 
      i = left; 
      j = right; 
      middle = Data[left]; 
      while(true) 
      { 
          while((i++)<right-1 && Data[i]<middle); 
          while((j--)>left && Data[j]>middle); 
          if(i>=j) 
              break; 
          temp = Data[i]; 
          Data[i] = Data[j]; 
          Data[j] = temp; //交换
      } 
      Data[left] = Data[j]; 
      Data[j] = middle; 
      if(left<j)  
        quick(Data,left,j); //递归调用
      if(right>i)  
        quick(Data,i,right); 
    } 

	//冒泡排序
	//效率 O(n²),适用于排序小列表
	public static void maopao(int Data[]){
		for(int i=0;i<Data.length;i++){
			for(int j=i+1;j<Data.length;j++){
				if(Data[i]>Data[j]){
					//下面是个人听别人说的一个很好用的小技巧 ^_^!
					Data[i]=Data[i]+Data[j];
					Data[j]=Data[i]-Data[j];
					Data[i]=Data[i]-Data[j];
				}
			}
		}
	}
	//选择排序
	//效率O(n²),适用于排序小的列表
	public static void choose(int Data[]){
		for(int i=0;i<Data.length-1;i++){
			int min=i;
			for(int j=i+1;j<Data.length;j++){
				if(Data[min]>Data[j]){
					//交换
					Data[min]=Data[min]+Data[j];
					Data[j]=Data[min]-Data[j];
					Data[min]=Data[min]-Data[j];
//					swap(Data[min],Data[j]);//为什么用不了呢 烦人
				}
			}
		}
	}
	
	//插入排序
	//最佳效率O(n);最糟效率O(n²)与冒泡、选择相同,适用于排序小列表 
	public static void insert(int Data[]){
		int left, cur;	    
		for (int i=1;i<Data.length;i++) {	       
			left=i-1;          //前一个数组元素	        
			cur=Data[i];     //给cur赋于Data[i]的值,将cur当做要插入的元素	        
			while (left>=0&&Data[left]>cur) { 	  	//(就是前一个的数组大于后一个数组)	             	                                                 				      
				Data[left+1]=Data[left];     //如果要插入的元素小于第j个元素,就将第j个元素向后移动	            
				left--;                    //跟再前一个数组元素比较	        
				}	        
			Data[left+1]=cur;   // 直到要插入的元素不小于第i-1个元素,将cur插入到数组中	    
				}		
	}
	//合并排序
	private static void mergeSort(int[] original) {
        if (original == null) {
            throw new NullPointerException("The array can not be null !!!");
        }
        int length = original.length;
        if (length > 1) {
            int middle = length / 2;
            int partitionA[] = Arrays.copyOfRange(original, 0, middle);// 拆分问题规模
            int partitionB[] = Arrays.copyOfRange(original, middle, length);
            // 递归调用
            mergeSort(partitionA);
            mergeSort(partitionB);
            sort(partitionA, partitionB, original);
        }
    }
    private static void sort(int[] partitionA, int[] partitionB, int[] original) {
        int i = 0;
        int j = 0;
        int k = 0;
        while (i < partitionA.length && j < partitionB.length) {
            if (partitionA[i] <= partitionB[j]) {
                original[k] = partitionA[i];
                i++;
            } else {
                original[k] = partitionB[j];
                j++;
            }
            k++;
        }
        if (i == partitionA.length) {
            while (k < original.length) {
                original[k] = partitionB[j];
                k++;
                j++;
            }
        } else if (j == partitionB.length) {
            while (k < original.length) {
                original[k] = partitionA[i];
                k++;
                i++;
            }
        }
    }
    private static void print(int[] array) {
        if (array == null) {
            throw new NullPointerException("The array can not be null !!!");
        }
        StringBuilder sb = new StringBuilder("");
        for (int element : array) {
            sb.append(element + " ");
        }
        System.out.println(sb.toString());
    }

	
	//主函数
    public static void main(String[] args){ 
    	int sum = 0;
    	System.out.println("1.快速排序   2.冒泡排序   3.选择排序  4.插入排序   5.合并排序");
    	Scanner sc =new Scanner(System.in);
        int n=sc.nextInt();
    	for(int i=10;i<1000000;i*=10){   		
    	 int[] Data = new int[i]; //定义数组
        for(int i1 = 0; i1< i; i1++) 
          Data[i1] = (int)(Math.random()*100); //随机生成数    
        System.out.println("数据规模为"+i+"时:"); 
        System.out.print("20组样本:");   
 //       for(int i = 0; i<Data.length; i++) 
 //           System.out.print(Data[i]+" "); //输出原始数据
        for(int j=0;j<20;j++){
        	long startTime = System.currentTimeMillis();    //获取开始时间	
        	switch(n){
        case 1:
   //     	System.out.println("快速排序:");         		
        		Paixu.quick(Data, 0, Data.length); //调用快排
        	
        break;
        case 2:
        	Paixu.maopao(Data);//调用冒泡
//        	System.out.println("\n冒泡排序");
//        	for(int i:Data)//遍历
//    		{
//    			System.out.print(i+" ");
//    		}
        	break;
        case 3:
        	Paixu.choose(Data);
 //       	System.out.println("\n选择排序");
//        	for(int i:Data)//遍历
//    		{
//    			System.out.print(i+" ");
//    		}
        	break;
        case 4:
        	Paixu.insert(Data);	 
//        	System.out.println("\n插入排序");
//        	for(int i:Data)//遍历
//    		{
//    			System.out.print(i+" ");
//    		} 
        	break;
        case 5:
//        	System.out.println("\n合并排序");
        	mergeSort(Data);
//            print(Data);
        	break;
      }
        	long endTime = System.currentTimeMillis();    //获取结束时间
        	int time=(int) (endTime - startTime);
        	System.out.print(time+" ");
        	sum +=time;     
        }   		
        System.out.println("\n"+"平均时间为"+(sum/20)+"ms");	 		
    	} 
    	sc.close();
    } 
}

运行结果:

  1. 测试:

  1. 运行结果

选择排序:

冒泡排序:

快速排序:

插入排序:

合并排序:

进行详细结果对比,得到结论:

 分析结果:

对比结果,实验分析:

方式/规模

10

100

1000

10000

100000

快速排序

0

0

0

3

45

冒泡排序

0

0

0

14

1449

选择排序

0

0

1

17

1442

插入排序

0

0

0

3

71

合并排序

0

0

0

1

7

3.对比得出结论:

选择排序:数据基本符合n2(二次增长)时间复杂度O(n2)

冒泡排序:数据基本符合n2(二次增长)时间复杂度O(n2)

快速排序:数据基本符合n(线性增长)时间复杂度O(n)

插入排序:数据基本符合n2(二次增长)时间复杂度O(n2)

合并排序:数据基本符合n(线性增长)时间复杂度O(n)

4.经验归纳:

以前很少用到方法,都是在主函数里乱写。觉得方法不好理解。这次用一个一个的方法分开实现一个一个功能,写完了之后觉得这种方式很方便。很有层次感。然而不足之处还是有很多,首先是自己编程确实不够熟悉,对于合并算法的理解还是不够透彻,实验中参考了网络,还有待好好改进。

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值