【插入希尔归并选择冒泡优化快排+重看递归】

## 排序算法


关于排序算法分析注意要点:

在这里插入图片描述

1、插入排序

打扑克:手里面大的是排好序的,另外是待排序的,一张一张插入后要保证有序
未插入的从已排序的末尾一个个往前比较,找到合适的位置插入(比较过的都往后面移动一位,刚好待排的当前元素被已排序的最后一个元素覆盖)。

public class InsertSort {
   public  static  void main(String[] args)
    {
        int[] a={9,8,7,6,5,4,0};
        int n=a.length;
        for(int i=1;i<n;i++)//默认0已经排好序了
        {
//            [8,9]
            int data=a[i];//防止i位置被移位的时候占用了
            int j;
            for(j=i-1;j>=0;j--)//去排好序的地方走
                //注意移位置是向后面移,所以从哪里开始比较!
            {
                if(a[j]>data)//比较对象是data,而非a[i]
                {
                    a[j+1]=a[j];//占用也站的是data所在的i位置
                }
                else
                {
                    break;//不用比较了
                }
            }
            a[j+1]=data;//跳出比较再赋值
            System.out.println("第"+i+"次比较结果");
            for(j=0;j<n;j++)
            {
                System.out.print(a[j]+" ");
            }
            System.out.println();
        }
    }

}

时间复杂度: o( n^2) 最好的情况:O(n);//每次都走break;内层时间O(1)
——如何优化?
分段,为了让break执行的越多越好,效率越高;

2、希尔排序:

这里是引用
在这里插入图片描述

   public static void main(String[] args) {
        int[] a = {9, 8, 7, 6, 5, 4, 0};
        int len = a.length;
        int add = len / 2;//7/2=3
        int i = 0;
        for(;add>=1;add/=2)//3/2=1
        {
            System.out.println("add="+add);
            for(i=add;i<len;i++)//i=1和插入排序一样
            {
                System.out.println("i="+i);
                int temp=a[i];
                int j=i;
                for(j=i-add;j>=0;j-=add)//j=9
                {
                    System.out.println("temp="+temp);
                    if(a[j]>temp)//9>6?
                    {
                        System.out.println("a[j]="+a[j]);
                        a[j+add]=a[j];//6=9
                        System.out.println(a[j]);

                    }
                    else{
                        break;//不需要再对j做-add了!!!!!!!!!!非常很重要
                    }
                }
                System.out.println("a[j+add]"+a[j+add]);
                a[j+add]=temp;//
//                System.out.println(temp);
                for(int k=0;k<len;k++)
                {
                    System.out.print(a[k]+" ");
                }
                System.out.println("___________");
            }


        }

3、归并排序

先分治,再合并在这里插入图片描述

public class MergeSort {
    /**
     * 1、分治最小长度为2
     * 2、比较大小交换位置
     * 3、两两合并
     */
    private int[] arr;
    public MergeSort(int[] inputarr) {
        arr = inputarr;
    }
    public void merge_sort() {
        int len = arr.length;
        int[] result = new int[len];
        merge_sort_execut(0, len - 1, result);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }


    }

    public void merge_sort_execut(int l, int r, int[] result) {
        if (l >= r)
            return;
        int len = r - l, mid = len / 2 + l;//安全写法
        int l1 = l, r1 = mid;
        int l2 = mid + 1, r2 = r;
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        *****merge_sort_execut(l1, r1, result);
        merge_sort_execut(l2, r2, result);
        //合并*****
        int index = l;
        while (l1 <= r1 && l2 <= r2) {
            result[index++] = arr[l1] < arr[l2] ? arr[l1++] : arr[l2++];
        }
        while (l1 <= r1) {
            result[index++] = arr[l1++];
        }
        while (l2 <= r2) {
            result[index++] = arr[l2++];
        }
        for (index = l; index <= r; index++) {
            arr[index] = result[index];
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}


4、选择排序
O(n^2)

1、分为有序和无序
2、从无序中找到最小值,排在有序的后面【和有序的后面那个元素交换——>因而‘不稳定’排序】

public static void main(String[] args)
    {
        int[] arr={9,1,8,7,6,5,4,3};
        int len=arr.length;
        for(int i=0;i<len;i++)//每个位置都判断
        {
                int minIndex = i;
                // 找到未排序部分中的最小元素的索引
                for (int j = i + 1; j < len; j++) {//找到里面最小的,也包括data[i],因而minindex=i
                    if (arr[j] < arr[minIndex]) {
                        minIndex = j;
                    }
                }
                // 将最小元素与未排序部分的第一个元素交换位置[不稳定排序]
                //可以加一个if(minIdex!=i)
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
        }
        for(int i=0;i<len;i++)
        {
           System.out.println(arr[i]);
        }

    }

5、冒泡排序
O(n^2)
1、每个泡泡都要处理
2、每次处理都是两两相邻的比较[稳定的,判断的时候用>,而非>=],将大的往后传递【最终每一趟都把最大的传递到最后面了】

    public static void main(String[] args)
    {
        int[] a={9,8,7,6,5,0};
        for(int i=0;i<a.length-1;i++)//循环次数【最后就剩一个泡泡了无需比较了,所以n-1】
        {
//
            for(int j=0;j<a.length-1-i;j++)//因为每一趟都把最大的移动到了最末尾,所以最后的就没有必要比较了,因而减去i
            {
                if(a[j]>a[j+1])
                {
                     int temp=a[j+1];//第三个变量
                     a[j+1]=a[j];
                     a[j]=temp;
//                   用加减[无需多一个变量]
//                    a[j+1]=a[j+1]+a[j];
//                    a[j]=a[j+1]-a[j];
//                    a[j+1]=a[j+1]-a[j];
                }

            }
        }
     for(int elem:a)
     {
         System.out.print(elem);
     }
    }

每一趟最坏的情况:每个都交换O(n^2);
如何优化?
对于与已经排好序的则变成了O(n);

			 boolean flag=false;
            for(int j=0;j<a.length-1-i;j++)//因为每一趟都把最大的移动到了最末尾,所以最后的就没有必要比较了,因而减去i
            {
                if(a[j]>a[j+1])
                {
                     int temp=a[j+1];//第三个变量
                     a[j+1]=a[j];
                     a[j]=temp;
//                   用加减
//                    a[j+1]=a[j+1]+a[j];
//                    a[j]=a[j+1]-a[j];
//                    a[j+1]=a[j+1]-a[j];
                    flag=true;//
                }
            }
            if(!flag)//无交换;说明相邻三的元素左《中《右
            {
                break;
            }

6、快速排序

1、找到一个基准,将数组分为{小于基准数的}+基准数+{大于基准数的};
logn次分割,每一次有n次的(基准)排序:O(nlogn)
2、如何实现?
3、为什么要区别右指针和左指针谁先走!
4、最坏的情况N次分治,N个排序:O(n^2)在这里插入图片描述
区别:在这里插入图片描述

public class FastSort {
    static int[] a = {9, 0, 8, 7, 5, 3, 6, 2};
    public static void main(String[] args) {
        fastsort_execut(a,0,a.length-1);
        for(int i=0;i<a.length;i++)
        {
            System.out.print(a[i]+" ");

        }

    }

    public static void fastsort_execut(int[] data,int l,int r) {

        int i = l;
        int j = r;
//        int basic=data[0];
        if(l>=r)
        {
            return;
        }
        int base = data[l];//注意必须先判断再给base赋值
        while (i<j)
        {
            while(i<j&&data[j]>=base)//!!!!!一定是右指针先迈出去
            {
                j--;
            }
            while(i<j&&data[i]<=base)
            {
               i++;
            }

            if(i<j)//一定要加上
            {//少一个变量的空间
                data[i]=data[i]+data[j];
                data[j]=data[i]-data[j];
                data[i]=data[i]-data[j];
            }
        }
        data[l]=data[j];
        data[j]=base;
//        for(int k=l;k<=r;k++)
//        {
//            System.out.print(data[k]);
//        }
//        System.out.println("中间结果");
//        int l1=0,r1=i-1,l2=i+1,r2=r;
        fastsort_execut(data,l,i-1);
        fastsort_execut(data,i+1,r);
    }
}

关于递归:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值