今日分数据结构作业:冒泡排序、堆排、希尔排序、快排……

版权声明: https://blog.csdn.net/King8611/article/details/82955096

先看实验报告:

 好吧,这次实验报告没有什么好吐槽的,安安分分的写了好久。

bug无数,虽然之前写过,但是没这么详细。

代码+注释:

import java.io.*;
import java.util.Arrays;
public class Main3 {
    /*直接排序,希尔排序,冒泡排序,快速排序,直接选择排序,堆排序,归并排序算法
     * 直接排序和直接选择排序不是同一个吗?
     * 太虚假了吧
     * 既然如此我就写一个好了
     */
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) {
        int arr[]=new int[10];                //测试一个1万数据的数组
        randomArrays(arr);
        long startTime,endTime;
        startTime = System.currentTimeMillis();
        chooseSort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("选择排序的时间是:"+(endTime-startTime)+"ms");
        upsetArrays(arr);
        startTime = System.currentTimeMillis();
        bubbleSort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("冒泡排序的时间是:"+(endTime-startTime)+"ms");
        upsetArrays(arr);
        startTime = System.currentTimeMillis();
        shellSort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("希尔排序的时间是:"+(endTime-startTime)+"ms");
        upsetArrays(arr);
        startTime = System.currentTimeMillis();
        memerySort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("归并排序的时间是:"+(endTime-startTime)+"ms");
        upsetArrays(arr);
        startTime = System.currentTimeMillis();
        heapSort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("堆排序的时间是:"+(endTime-startTime)+"ms");
        upsetArrays(arr);
        startTime = System.currentTimeMillis();
        quickSort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("快排的时间是:"+(endTime-startTime)+"ms");
        upsetArrays(arr);
        startTime = System.currentTimeMillis();
        Arrays.sort(arr);
        endTime = System.currentTimeMillis(); 
        System.out.println("JAVA类库自带快速的时间是:"+(endTime-startTime)+"ms");
    }
//选择排序=====================================================================================================
    /*
     * 柿子先挑软的捏,当然要先写选择排序
     */
    static void chooseSort(int arr[]) {
        for(int i=0;i<arr.length;i++) {
            for(int j=i+1;j<arr.length;j++) {
                if(arr[i]>arr[j]) {
                    swap(arr,i,j);
                }
            }
        }
    }
//============================================================================================================

//冒泡排序=====================================================================================================
    /*
     * 冒泡排序
     * 加个flag优化一下
     */
    static void bubbleSort(int arr[]) {
        boolean flag=true;
        for(int i=0;i<arr.length&&flag;i++) {
            flag=false;
            for(int j=arr.length-1;j>i;j--) {
                if(arr[j]<arr[j-1]) {
                    flag=true;
                    swap(arr,j,j-1);
                }
            }
        }
    }
//=============================================================================================================
    
//希尔排序=====================================================================================================
    /*
     * 希尔排序
     * 这个排序挺有趣的,刚才看了一个视频理解了:
     * https://www.bilibili.com/video/av17062242?from=search&seid=2961680739883013473
     * 不过下一个视频也挺有趣的
     * https://www.bilibili.com/video/av17004970/?spm_id_from=trigger_reload
     * 代码我自己实现一下,不行可以调试,或者看别人的。
     * 这个排序不太稳定
     * 不过我很奇怪这个原理
     */
    static void shellSort(int arr[]) {
        int len=arr.length;
        int gap=len;                                //过程增量
        do {
            gap=gap/3+1;
            for(int i=0;i<len-gap;i++) {
                if(arr[i]>arr[i+gap]) {
                    int j=i;
                    while(j>=0&&arr[j]>arr[j+gap]) {
                        swap(arr,j,j+gap);
                        j-=gap;
                    }
                }
            }
        }
        while(gap>1);
        // 写下了感觉还是很简单的,而且测试发现也没什么问题。         
    }
//=============================================================================================================

//归并排序=====================================================================================================
    /*
     * 归并排序还是很好用的,很稳定的。
     * 记得刚加入ACM的时候,学长就是通过选择排序和归并排序给我们讲复杂度
     * 这个在我大一上学期自己实现了一下,觉得也没有什么难度。
     * 很经典的分治递归
     */
    static void memerySort(int arr[]) {
        int[] temp=new int[arr.length];
        memerySort(arr,0,arr.length-1,temp);
    }
    static void memerySort(int arr[],int l,int r,int temp[]) {
        int t=(l+r)>>1;                    //位运算,(x>>1)==x/2。计算比较快,堆排应该会用到比较多的位运算
        if(l==r)
            return;
        memerySort(arr,l,t,temp);
        memerySort(arr,t+1,r,temp);
        memeryArrays(arr,l,r,t,temp);
    }
    static void memeryArrays(int arr[],int l,int r,int t,int temp[]) {
        int i=l,j=t+1;
        int now=0;
        while(i<=t&&j<=r) {
            if(arr[i]<arr[j]) 
                temp[now++]=arr[i++];
            else
                temp[now++]=arr[j++];
        }
        for(;i<=t;i++) {
            temp[now++]=arr[i];
        }
        for(;j<=r;j++) {
            temp[now++]=arr[j];
        }
        for(int k=l;k<=r;k++) {
            arr[k]=temp[k-l];
        }
    }
//=============================================================================================================

//堆排序=======================================================================================================
    /*
     * 堆排这东西,每次都是写bug10分钟。debug两小时。东西太多了,思路太严谨了。
     * 虽然写过好几次吧
     * 我本来以为堆排一定要额外开一个堆,没想到看了网上的思路,不一定是这样的
     * 很节省空间啊
     * 大概就是,需要一个adjust函数调整堆(如果要从小排序,需要挑成最大堆)
     * 把这个无序数组调整成堆
     * 然后把堆顶和数组最后一个元素交换,堆容量-1
     * 这样每次都把堆里最大一个元素放到了最后面,就排好序了
     * 其实我感觉堆排严谨的复杂度应该是n*logn!
     */
    static void heapSort(int[] arr) {
        buildHeap(arr);                //建堆
        getSort(arr);                //排序
    }
    //需要从下向上调整
    static void buildHeap(int[] arr) {
        for(int i=(arr.length-2)/2;i>=0;i--) {
            adjustHeap(arr,i,arr.length);
        }
    }
    static void getSort(int[] arr) {
        for(int i=arr.length-1;i>=1;i--) {
            swap(arr,0,i);
            adjustHeap(arr,0,i);
        }
    }
    //i是调整节点为i的点,len是堆容量
    static void adjustHeap(int arr[],int i,int len) {
        while((i<<1|1)<len) {
            int left=i<<1|1,right=(i<<1)+2;
            if(right<len&&arr[right]>arr[i]&&arr[right]>arr[left]) {
                swap(arr,i,right);
                i=right;
            }
            else if(arr[left]>arr[i]) {
                swap(arr,i,left);
                i=left;
            }
            else
                break;
        }
    }
//=============================================================================================================
    
//快排=========================================================================================================
    /*
     * 安利一篇文章,挺不错的
https://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=2651005737&idx=1&sn=924250b9065f44f5f
8c7b026ff914fcc&chksm=8bad90debcda19c8fc016c5968d4c817b16c736c0a2c9a5de378ddac1c82b5c4df446
dbeb8e1&mpshare=1&scene=23&srcid=0910GbfDP3XhEWpCqgfK2Ffc#rd
     */
    static void quickSort(int[] arr) {
        quickSort(arr,0,arr.length-1);
    }
    static void quickSort(int[] arr,int l,int r) {
        if(l>=r)
            return;
        int privot=partition(arr,l,r);
        quickSort(arr,l,privot-1);
        quickSort(arr,privot+1,r);
    }
    static int partition(int[] arr,int start,int end) {
        int l=start,r=end;
        int pivot=arr[start];
        while(l!=r) {
            while(l<r&&arr[r]>pivot) {
                r--;
            }
            while(l<r&&arr[l]<=pivot) {
                l++;
            }
            if(l<r) {
                swap(arr,l,r);
            }
        }
        if(l!=start)
            swap(arr,l,start);
        return l;
    }
//=============================================================================================================
    
    //打印一个数组,方便测试
    static void print(int arr[]) {
        for(int i=0;i<arr.length;i++) {
            out.write(arr[i]+" ");
        }
        out.write("\n");
        out.flush();
    }
     //随机生成一个数组,方便测试
    static void randomArrays(int arr[]) {
        for(int i=0;i<arr.length;i++)
            arr[i]=(int) (Math.random()*1000);
    }
    //随机打乱一个数组,方便测试
    static void upsetArrays(int[] arr) {
        for(int i=0;i<arr.length;i++) {
            int t=(int) (Math.random()*arr.length);
            if(i!=t)
                swap(arr,i,t);
        }
    }
    //异或运算交换两个变量,比较节省时间。
    static void swap(int arr[],int a,int b) {
        arr[a]^=arr[b];
        arr[b]^=arr[a];
        arr[a]^=arr[b];                    
    }
}
/*
 *1000的数据量
 *选择排序的时间是:4ms
 *冒泡排序的时间是:5ms
 *希尔排序的时间是:1ms
 *归并排序的时间是:1ms
 *堆排序的时间是:0ms
 *快排的时间是:1ms
 *JAVA类库自带快速的时间是:1ms

 *1w的数据量
 *选择排序的时间是:59ms
 *冒泡排序的时间是:150ms
 *希尔排序的时间是:3ms
 *归并排序的时间是:2ms
 *堆排序的时间是:3ms
 *快排的时间是:3ms
 *JAVA类库自带快速的时间是:5ms

 *5W的数据量
 *选择排序的时间是:1391ms
 *冒泡排序的时间是:3770ms
 *希尔排序的时间是:10ms
 *归并排序的时间是:11ms
 *堆排序的时间是:12ms
 *快排的时间是:20ms
 *JAVA类库自带快速的时间是:9ms
 
 *10W的数据量
 *选择排序的时间是:4915ms
 *冒泡排序的时间是:15191ms
 *希尔排序的时间是:17ms
 *归并排序的时间是:20ms
 *堆排序的时间是:17ms
 *快排的时间是:18ms
 *JAVA类库自带快速的时间是:10ms

 *1千万的数据,选择排序和冒泡排序不敢玩了,就搞下这些。
 *希尔排序的时间是:1835ms
 *归并排序的时间是:1181ms
 *堆排序的时间是:2030ms
 *快排的时间是:15282ms
 *JAVA类库自带快速的时间是:500ms

 *由此可见,数组的容量越大,差距越大,还是系统自带的好用,哈哈哈
 */

猜你喜欢

转载自blog.csdn.net/King8611/article/details/82955096
今日推荐