排序算法总结

1.桶排序

public static void BucketSort(int[] nums){
        //这里需要知道数组的最大值,作为桶的个数
        int[] buckets = new int[11];
        //装桶
        for (int i = 0; i < nums.length; i++) {
            buckets[nums[i]]++;
        }
        int j = 0;
        //出桶
        for (int i = 0; i < buckets.length; i++) {
            while (buckets[i]>0)
            {
                nums[j] = i;
                j++;
                buckets[i]--;
            }
        }
        System.out.println(Arrays.toString(nums));
    }

2.冒泡排序

public static void Bubble(int[] nums){
        /*
        冒泡和选择的区别是:
        冒泡是从上到下依次确定好每个位置的数字,每次把较小的数字交换到上边
        选择是每次找到最小数字,然后放到应该的位置
         */
        //冒泡次数是数组长度,每次冒泡都确定顶部一个位置的数字
        for (int i = 0; i < nums.length-1; i++) {
            //每次都是从数组底部开始取,依次向上
            for (int j = nums.length-1; j > i ; j--) {
                if (nums[j]<nums[j-1])
                {
                    int temp = nums[j];
                    nums[j] = nums[j-1];
                    nums[j-1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(nums));
    }

3.选择排序

public static void SelectionSort(int[] nums){
        //每次从当前最开始位置(每次都往下一个)开始,找到最小的数,排到上边
        for (int i = 0; i < nums.length-1; i++) {
            //记录最小数的index
            int min = i;
            for (int j = i+1; j < nums.length; j++) {
                //更新最小数index
                if (nums[j]<nums[min])
                    min = j;
            }
            //找到最小数后交换
            if (i!=min)
            {
                int temp = nums[min];
                nums[min] = nums[i];
                nums[i] = temp;
            }
        }
        System.out.println(Arrays.toString(nums));
    }

4.三数取中快排

public static void QuickSort(int[] nums,int lo,int hi){
        if (lo>=hi) return;
        //三数取中进行选择基准值
        int mid = (lo+hi)/2;
        if (nums[mid]>nums[hi])
            swap(mid,hi,nums);
        if (nums[lo]>nums[hi])
            swap(lo,hi,nums);
        if (nums[mid]>nums[lo])
            swap(lo,mid,nums);
        //现在lo位置是中间数
        int left = lo;
        int right = hi;
        while (lo<hi)
        {
            //必须从基准对面开始走,因为对面哨兵停止的位置应该和基准位置交换
            while (nums[hi]>=nums[left] && lo<hi)
                hi--;
            while (nums[lo]<=nums[left] && lo<hi)
                lo++;
            //交换不符合者
            swap(lo,hi,nums);
        }
        swap(hi,left,nums);
        QuickSort(nums,left,hi-1);
        QuickSort(nums,hi+1,right);
    }
    public static void swap(int i,int j,int[] nums){
        int temp = nums[j];
        nums[j] = nums[i];
        nums[i] = temp;
    }

 5.归并排序

/*
    思路就是将两个有序数组进行组合,通过递归得到左右排序好的数组
     */
    //组合函数
    public void combine(int[] a,int sta,int mid,int end,int[] res)
    {
        int f = sta;
        int sta2 = mid+1;
        int i = 0;
        //两个数组都没有遍历完
        while (sta<=mid&&sta2<=end)
        {
            if (a[sta]<a[sta2]) res[i++] = a[sta++];
            else res[i++] = a[sta2++];
        }
        while (sta<=mid) res[i++] = a[sta++];
        while (sta2<=end) res[i++] = a[sta2++];
        //将排序结果添加到a中,让a形成有序数组
        for (int j = 0; j < i; j++) {
            a[j+f] = res[j];
        }
    }
    public void sort(int[] a ,int sta,int end,int[] res)
    {
        //分治思想把子数组排为有序数组
        if (sta<end)
        {
            int mid = (sta+end)/2;
            sort(a,sta,mid,res);
            sort(a,mid+1,end,res);
            combine(a,sta,mid,end,res);
        }
    }
    public void mergeSort(int[] a)
    {
        int[] res = new int[a.length];
        sort(a,0,a.length-1,res);
    }

6.堆排序

public void sort(int[] nums)
    {
        //要设置一个变量记录当前堆的大小,每次取数,堆会少最后一个节点
        int l = nums.length;
        //构建大根堆,降序则构建小根堆。大根堆是一个完全二叉树,且父节点一定不小于子节点
        //数组一开始可以看成一个堆,不过需要调整。从最后一个非叶节点开始调整,调整到根节点
        //最后一个非叶节点的index是n/2-1;
        for (int i = (l/2)-1; i >=0 ; i--) {
            adjust(nums,i,l);
        }
        //开始取数
        while (l>1){
            //取数就是把最大的数(堆顶)放到最后,然后最后那个节点就脱离堆(尺寸-1)
            swap(nums,0,l-1);
            l--;
            //每次交换结束都要进行调整
            adjust(nums,0,l);
        }
    }
    public void adjust(int[] nums,int index,int size){
        /*
        输入的是待调整堆和调整范围(从index节点处开始调整,默认前边是调整好的)
         */
        //获取完全二叉树中子节点的index
        int l = index*2+1;
        int r = index*2+2;
        int max = index;
        //找到这一家庭中最大值是谁,有可能有的孩子不存在,所以要判断
        if (l<size && nums[max]<nums[l]) max = l;
        if (r<size && nums[max]<nums[r]) max = r;
        //如果需要调整,就调整
        if (max!=index)
        {
            swap(nums,max,index);
            //调整后有可能被调整的子节点会不符合规定,所以要调整孩子节点
            adjust(nums,max,size);
        }
    }
    public void swap(int[] nums,int i,int j)
    {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

 7.插入排序

public void sort(int[] nums){
        /*
        从前两个开始,排好序,以后从第三个开始后,前边的就是都排好的了,大的数往后挪,知道找到当前数的位置
         */
        if (nums.length<2) return;
        //外层代表当前数
        for (int i = 1; i < nums.length; i++) {
            int temp = nums[i];
            int j = i-1;
            while (j>=0&&temp<nums[j])
            {
                nums[j+1] = nums[j];
                j--;
            }
            nums[j+1] = temp;
        }
    }

8.希尔排序,希尔排序是在插入排序的基础上做的优化

请看大牛整理的:https://www.cnblogs.com/chengxiao/p/6104371.html

posted @ 2018-03-06 22:08  stAr_1  阅读(224)  评论(0编辑  收藏  举报