数据与结构(一)排序

参考https://blog.youkuaiyun.com/hellozhxy/article/details/79911867
有动图展示排序过程,但有一定的瑕疵。
冒泡排序:

//冒泡排序
    //以从小到大为例,比较相邻的元素,如果第一个比第二个大,交换位置
    //对每一对相邻元素进行同样的操作,对每一个元素除了最后一个元素,进行上诉操作
    // 最佳 n 平均n^2 最坏 n^2
    public static int[] bubbleSort(int[] arr){
        if(arr.length==0){
            return  arr;
        }
        for(int i=0;i<arr.length;i++){
            for(int j=0;j<arr.length-1-i;j++){
                if(arr[j]>arr[j+1]){
                    arr[j]^=arr[j+1];
                    arr[j+1]^=arr[j];
                    arr[j]^=arr[j+1];
                    /*arr[j]=arr[j]^arr[j+1];
                    arr[j+1]=arr[j]^arr[j+1];
                    arr[j]=arr[j]^arr[j+1];*/
                }
            }
        }
        return arr;
    }

这里的元素交换我使用了一下位运算的异或交换,即一个数对同一个数连续异或三次为它本身这个规律,但存在一个bug,就是当地址相同的两个数异或的话,异或会归零。

//选择排序
    //每次遍历选择最小的一个放在数组起始位置
    //最佳情况:T(n) = O(n)   最差情况:T(n) = O(n2)   平均情况:T(n) = O(n2)
    public static int[] selectSort(int[] arr){
        if(arr.length==0){
            return arr;
        }
        for(int i=0;i<arr.length;i++){
            int minIndex=i;
            for(int j=i;j<arr.length;j++){
                if(arr[j]<arr[minIndex]){
                    minIndex=j;
                }
            }
            int tem=arr[i];
            arr[i]=arr[minIndex];
            arr[minIndex]=tem;
            //使用异或时,如果地址相同的异或会清零。
           /* arr[i]=arr[i]^arr[minIndex];
            arr[minIndex]=arr[i]^arr[minIndex];
            arr[i]=arr[i]^arr[minIndex];*/
        }
        return arr;
    }
//插入排序
    //构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
    //最佳情况:T(n) = O(n)   最坏情况:T(n) = O(n2)   平均情况:T(n) = O(n2)
    public static int[] InsertionSort(int[] arr){
        if(arr.length==0) {
            return arr;
        }
        for(int i=0;i<arr.length;i++){
        int current=arr[i+1];
        int preIndex=i;
        while(preIndex>=0 && current<arr[preIndex]){
            arr[preIndex+1]=arr[preIndex];
            preIndex--;
        }
        arr[preIndex+1]=current;
        }
        return arr;
    }
//希尔排序;缩小增量排序
    //希尔增量序列:{n/2,(n/2)/2...1}
    //增加一个增量序列,然后进行插入排序
    //最佳情况:T(n) = O(nlog2 n)  最坏情况:T(n) = O(nlog2 n)  平均情况:T(n) =O(nlog2n)
    public static int[] shellSort(int[] arr){
        if(arr.length==0){
            return arr;
        }
        int len=arr.length;
        int temp,gap=len/2;
        while (gap>0){
            for(int i=gap;i<len ;i++){
                temp=arr[i];
                int preIndex=i-gap;
                while (preIndex>=0 && arr[preIndex]>temp){
                arr[preIndex+gap]=arr[preIndex];
                preIndex-=gap;
                }
                arr[preIndex+gap]=temp;
            }
            gap/=2;
        }
        return arr;
    }

 //归并排序
    //最佳情况:T(n) = O(n)  最差情况:T(n) = O(nlogn)  平均情况:T(n) = O(nlogn)
    //代价是需要额外的内存空间。
    // 把长度为n的输入序列分成两个长度为n/2的子序列;
    //对这两个子序列分别采用归并排序;
    //将两个排序好的子序列合并成一个最终的排序序列。
    // 若将两个有序表合并成一个有序表,称为2-路归并。
    public static int[] mergeSort(int[] arr){
        if(arr.length<2) return arr;
        int mid=arr.length/2;
        int[] left=Arrays.copyOfRange(arr,0,mid);
        int[] right=Arrays.copyOfRange(arr,mid,arr.length);
        return merge(mergeSort(left),mergeSort(right));
    }
    public static int[] merge(int[] left,int[] right){
        int[] result=new int[left.length+right.length];
        for(int index=0,i=0,j=0;index<result.length;index++){
         if(i>=left.length){
             result[index]=right[j++];
         }
         else if(j>=right.length){
         result[index]=left[i++];
         }
         else if(left[i]>right[j]){
             result[index]=right[j++];
         }
         else {
             result[index]=left[i++];
         }
        }
        return result;
    }

//快速排序
    //最佳情况:T(n) = O(nlogn)   最差情况:T(n) = O(n2)   平均情况:T(n) = O(nlogn) 
    //从数列中挑出一个元素,称为 “基准”(pivot);
    //重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
    //重复上诉过程,直到整体有序
    public static int[] quickSort1(int[] arr,int left,int right){
        if(left<right){
            int index=partition1(arr,left,right);
            quickSort1(arr,left,index-1);
            quickSort1(arr,index+1,right);
        }
        return arr;
    }
    public static int partition1(int[] arr,int l,int r){

        //默认是第一个
        int key=arr[l];
//        //可以做一个优化
//        int index=l+(int)(Math.random()*(r-l+1));
////        int key=arr[index];
        while(l<r){
            while(l<r&&key<=arr[r]){
                r--;
            }
            arr[l]=arr[r];
            while(l<r&&key>=arr[l]){
                l++;
            }
            arr[r]=arr[l];
        }
        arr[l]=key;
        return l;
    }

这个快速排序是教科书上的基本实现,如果使用随机索引的方式,要使用交换。

//堆排序
    //最佳情况:T(n) = O(nlogn) 最差情况:T(n) = O(nlogn) 平均情况:T(n) = O(nlogn)
    //建堆,满足完全二叉树的性质:左边子节点位置 = 当前父节点的两倍 + 1,右边子节点位置 = 当前父节点的两倍 + 2
    //交换堆顶与数组最后一个元素
    static int len;
    public static int[] heapSort(int[] arr){
        len=arr.length;
        if(len<1){
            return arr;
        }
        buildMaxHeap(arr);
        while(len>0){
            swap(arr,0,len-1);
            len--;
            adjustHeap(arr,0);
        }
        return arr;
    }

    public static void buildMaxHeap(int[] arr) {
        for(int i=(len-1)/2;i>=0;i--){
            adjustHeap(arr,i);
        }
    }
    public static void adjustHeap(int[] arr, int i) {
    int maxIndex=i;
    if(i*2<len&&arr[i*2]>arr[maxIndex]){
        maxIndex=i*2;
    }
    if(i*2+1<len&&arr[i*2+1]>arr[maxIndex]){
        maxIndex=i*2+1;
    }
    if(maxIndex!=i){
        swap(arr,maxIndex,i);
        adjustHeap(arr,maxIndex);
    }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值