算法第一部分(1)

算法相关

1.学习算法,最好先了解数组,链表,堆,栈等线性结构
2.对递归,遍历,算法复杂度有着常识性理解
3.主要包括三方面的知识:线性(主要是排序) — 树形结构 — 图形结构

选择排序法

定义:选择排序每次都从剩下的n - i 个元素找到最小的数,并与i位置的数交换位置。

public  void selectionSort(T[] arr,int n){
        for (int i = 0;i < n;i ++){
            int minIndex = i;
            //查找出 i+1 到 n 的最小值并放到第一位
            for (int j = i + 1;j < n; j ++){
                if(arr[j] .compareTo(arr[minIndex])<0){
                    minIndex = j;
                }
            }
            swap(arr,i,minIndex);

        }

    }

选择排序法的复杂度是O(N*N) 需要对n个数进行排序,每个数的排序需要遍历(n … 1)次

插入排序法

定义:插入排序法循环n次,每次将第i + 1个数与i及其前面的数进行对比。如果i+ 1 < i 则需要进行交换。

//插入排序
    public  void insertSort(T[] arr,int n){
        for (int i = 0;i < n;i ++){
            //寻找元素arr[i]合适的插入位置
            //优化每一次循环都要大量交换的问题
            T e=arr[i];
            int j;
            for ( j = i;j>0 && arr[j-1].compareTo(e) > 0;j--){
                arr[j] = arr[j-1];
            }
            arr[j] = e;
        }
    }

归并排序

定义:归并排序将一个数组进行递归二分,直到无法再细分下去后,排序并向上合并

public void mergeSort(T[] arr,int n){
        mergeSort(arr,0,n-1);
    }

    //递归使用归并排序,对arr【l。。。r】的范围进行排序
    private void mergeSort(T[] arr, int l, int r) {
        //先处理递归到底的情况,即当前区间只剩下一个数的情况
        if(l >= r){
            return;
        }
        //当前区间的中间值。
        int mid = l+(r - l ) / 2; //(l + r) / 2可能发生溢出
        //先将mergeSort归并到 0 0
        mergeSort(arr,l,mid);
        //再将其归并到 0 1
        mergeSort(arr,mid + 1,r);
        //归并已经排序好的两部分函数,只要这样就不需要排序
        if(arr[mid] .compareTo(arr[mid + 1]) > 0){
            mergeSort(arr,l,mid,r);
        }

    }


    //将arr[l...mid]和arr[mid+1...r]两部分进行归并
    private void mergeSort(T[] arr, int l, int mid, int r) {
       T[] aux = (T[])new Comparable[r - l + 1];
       // 0 - 2
       for (int i = l;i <= r;i ++){
           //这边又一个i - l的偏移量 aux需要从 0 开始
           aux[i - l] = arr[i];
       }

       //指定两个数组的开头
       int i = l,j = mid + 1;
       for (int k = l ; k <= r ; k ++){

           if(i > mid){
               //如果i已经遍历完全
               arr[k] = aux[j - l];
               j ++;
           }else if(j > r){
               //如果j已经遍历完全
               arr[k] = aux[i -l];
               i ++;
           } else if(aux[i - l] .compareTo(aux[j - l]) < 0){
               //aux需要从 0 开始
               arr[k] = aux[i - l];
               i ++;
           }else{
               arr[k] = aux[j - l];
               j ++;
           }
       }
    }

归并排序同时也可以采用自底向上的方法

public void mergeSortTwo(T[] arr,int n){
        //整个数组的大小
        for (int sz = 1;sz <= n;sz += sz){
            //对arr[i .... i+sz-1] 和 arr[i + sz ...i+2*sz-1] 进行归并
            //需要解决 i + sz -1 与 i + sz + sz -1 可能越界的问题
            for (int i = 0;i + sz < n;i += sz + sz){
                  mergeSort(arr,i,i + sz - 1,i + sz + sz -1< n - 1?i+sz+sz-1:n - 1);
            }
        }
    }

快速排序

定义:快速排序即随机找出一个点V,并把其他的点区分为小于V与大于V,即把一个数组分为三部分,递归排序出该数组
在这里插入图片描述
注意,当数组中包含大量重复键值,两边数组依然有可能极不平衡,可以采用把重复值V随机分到两边来解决这个问题

public void quickSort2(T[] arr,int n){
        quickSort2(arr,0,n-1);
    }

    private void quickSort2(T[] arr, int l, int r) {
        if(l >= r){
            return;
        }

        int p =partition2(arr,l,r);
        quickSort2(arr,l,p - 1);
        quickSort2(arr,p+1,r);
    }

    private int partition2(T[] arr, int l, int r) {
        Random random=new Random();
        swap(arr,l,random.nextInt(r -l + 1) + l);
        T v = arr[l];

        //arr[l+1...j] <=v; arr[j...r] >= v
        int i = l + 1,j = r;
        while (true){
            //i会停在第一个arr[i] > v 上,i从前往后遍历
            while (i <= r && arr[i].compareTo(v) < 0){ i++;}
            //j 会停在第一个arr[j] < v上,j从后往前遍历
            while (j >= l+1 && arr[j].compareTo(v) > 0){
                j -- ;
            }
            //判断循环是不是结束了
            if(i > j){
                break;
            }
            swap(arr,i,j);
            i++;
            j--;
        }
        swap(arr,l,j);
        return j;
    }

同时还有三路快速排序,分为大于v 等于v 小于v 三个部分
在这里插入图片描述

public void quickSort3(T[] arr,int n){
        quickSort3(arr,0,n-1);
    }

    private void quickSort3(T[] arr, int l, int r) {
        if(l >= r){
            return;
        }

        Random random=new Random();
        //随机一个数与第一个数交换,防止近乎有序的数组<V与>V两边极平衡度差
        swap(arr,l,random.nextInt(r -l + 1) + l);
        T v = arr[l];
        int lt = l;//arr[l + 1 ... lt] <v;
        int gt =r + 1;//arr[gt .. r] >v
        int i = l + 1;//arr[lt+1...i] == v
        while (i < gt){
            if(arr[i].compareTo(v) < 0){
                swap(arr,i,lt + 1);
                lt ++;
                i ++;
            }else if(arr[i].compareTo(v) > 0){
                swap(arr,i,gt - 1);
                gt -- ;
            }else{
                i++;
            }
        }
        swap(arr,l,lt);
        quickSort3(arr,l,lt - 1);
        quickSort3(arr,gt,r);

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值