简单的排序算法和二分查找

1.二分查找

1.前提:有已排序数组A(假设已经做好)
2.定义左边界left、右边界 right,确定搜索范围,循环执行二分查找(3、4两步)

3.获取中间索引mid=Floor((left+right) /2)

4.中间索引的值 A[mid]与待搜索的值T进行比较

4.1 A[mid]==T表示找到,返回中间索引

4.2 A[mid>T,中间值右侧的其它元素都大于T,无需比较,中间索引左边去找,mid-1设置为右边界,重新查找

4.3 A[mid]<T,中间值左侧的其它元素都小于T,无需比较,中间索引右边去找,mid+1设置为左边界,重新查找

5.当left>right时,表示没有找到,应结束循环

    public static int binarySearch(int[]a,int p){
        int left=0,right=a.length,mid;//定义边界值,步骤2
        while(left<=right){//跳出循环的清空 步骤5

            mid=(left+right)/2;//定义mid值 步骤3
            if(a[mid]==p){//步骤4.1
                return mid;
            }else if(a[mid]>p){//4.2
                right=mid-1;
            }else {//4.3
                left=mid+1;
            }
        }
        return -1;//没找到返回-1
    }

其中步骤3还可以优化一下,比如说 left+right 超过了限制 则会出现错误,byte 的最大值就是128 超过了就出错了。

优化方法如下:(left+right)/2 ==> left+(right-left/2);或者是(left+right)>>>2

上述2种都可以解决错误

在做选择填空题时,奇数个二分取中间,偶数个二分取中间靠左

2.冒泡排序

1.依次比较数组中相邻元素大小,若A[j]>A[j+1],则交换两个元素,两两都比较一边称之为一轮冒泡,结果是让最大的元素排至最后

2.重复以上步骤,直至整个数组有序

    public static  void bubble(int []a){
        for (int j = 0; j < a.length-1; j++) {//n轮冒泡
            for (int i = 0; i < a.length-1; i++) {//1轮冒泡
                if (a[i] > a[i + 1]) {
                    int t = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = t;
                }
            }
        }
    }

上面的算法还可以优化,比如说 有部分的数据本来就有次序,就不用比较了

    public  static void bubble(int[]a) {
        for (int j = 0; j < a.length - 1; j++) {
            boolean flag=false;//flag在这里的作用是如果下面交换数据没有执行,则跳出循环,
            //没有执行则意味着后面已经排好序了
            for (int i = 0; i < a.length - 1-j; i++) {
                if (a[i] > a[i + 1]) {
                    int t=a[i];
                    a[i]=a[j];
                    a[j]=t;
                    flag=true;
                }
            }
            if (!flag){
                break;
            }
        }
    }

还可以继续优化 ,上面是优化排序的轮数,下面的就是优化一轮排序的比较次数

 public  static void bubble2(int[]a) {
        int n=a.length-1;//n是要比较的长度就是一轮冒泡两两比较的次数
        do {
            int last = 0;//last 就是最后一个不用比较的位置的索引
            /*
        比如说 2 1 3 4 7 5  8 9 10
        第一层冒泡后 8 9 10 都是不用排序的 所以此时 下一次冒泡要比较的此时 也就是for循环中的n就会变成了
        此时5的索引,下一次只需要两两比较到5的位置即可
         */
            for (int i = 0; i < n; i++) {//比较一次
                if (a[i] > a[i + 1]) {
                    int t = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = t;
                    last = i;
                }
            }
            n = last;
        } while (n != 0);
    }

3.选择排序

1.将数组分为两个子集,排序的和未排序的,每一轮从未排序的子集中选出最小的元素,放入排序子集

2.重复以上步骤,直至整个数组有序

   public static void selection(int[]a){
        for (int i = 0; i <a.length-1 ; i++) {
            int s=i;
            for (int j = s+1; j < a.length; j++) {
                if (a[s]>a[j]){
                    s=j;
                }
            }
            if (s!=i){
                int t=a[s];
                a[s]=a[i];
                a[i]=t;
            }
        }
    }

选择排序与冒泡排序相比较,

1.两者的时间复杂度都是O(n^2);

2.选择排序一般要快于冒泡,因为其交换次数少

3.但如果集合有序度高,冒泡则会优于选择

4.冒泡属于稳定排序算法,而选择属于不稳定排序算法

4.插入排序

1.将数组分为两个区域,排序区域和未排序区域,每一轮从未排序区域中去出第一个元素,插入到排序区域,需要保证顺序

2.重复以上步骤,直至整个数组有序

  public static void InsertSort(int[]a){
        for (int i = 1; i < a.length; i++) {
            int t=a[i];
            int j=i-1;
            while (j>=0){
                if (t<a[j]){
                    a[j+1]=a[j];
                }else {
                    break;
                }
                j--;
            }
            a[j+1]=t;
        }
    }

插入排序与选择排序比较

1.两者平均时间复杂度都素O(n^2)

2.大部分清空下,插入都优于选择,

3.有序集合插入的时间复杂度为O(n)

4.插入属于稳定排序算法,而选择属于不稳定排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值