SQL面试50题 数据库准备(存储过程)

時小白

关注

阅读 8

2024-12-02

六大排序算法

一.插入排序

1.1 直接插入排序

  public static void insertSort(int[] array){
        for(int i=1;i<array.length;i++){//由数组1下标开始进行比较
            int tmp=array[i];
            int j=i-1;
            for(;j>=0;j--){
                if(tmp<array[j]){
                    array[j+1]=array[j];//将j放入j+1位置
                }else{
                //进入else则为有序,break跳出嵌套循环
                    break;
                }
            }
      //当嵌套的for循环一直在比较最小值tmp,知道为-1跳出循环,这里需要j+1
      //当大于时候,因为i-1赋值给j,break跳出后j需要+1下标值得到tmp
            array[j+1]=tmp;
        }
    }

1.2 希尔排序

   public static void shellSort(int[] array){
        int gap=array.length;
        while(gap>1){
            gap/=2;//将数组/2,有多组变少组直到为1
            shell(array,gap);
        }
    }
    public static void shell(int[] arr,int gap){
    //从gap开始遍历
        for(int i=gap;i<arr.length;i++){
        //获取gap下标的值
            int tmp=arr[i];
            求i-gap个差距得到j值
            int j=i-gap;
            for(;j>=0;j-=gap){
                if(tmp<arr[j]){
                    arr[j+gap]=arr[j];
                }else{
                    break;
                }
            }
            arr[j+gap]=tmp;
        }
    }

二.选择排序

2.1 单向选择排序

   public static void selectSort2(int[] array){
        for(int i=0;i<array.length;i++){
            int minIndex=i;

            for(int j=i+1;j<array.length;j++){
                if(array[j]<array[minIndex]){
                    minIndex=j;
                }
            }
            swap(array,minIndex,i);
        }
    }

2.2双向选择排序

在这里插入图片描述

 public static void selectSort(int[] array){
        //起始位置和末尾的下标值
        int left=0;
        int right=array.length-1;
        while(left<right){
            //都从0下标开始比较
            int maxIndex=left;
            int minIndex=left;
            for(int i=left+1;i<=right;i++){
                if(array[i]<array[minIndex]) minIndex=i;
                if(array[i]>array[maxIndex]) maxIndex=i;
            }
            swap(array,left,minIndex);
            //如果0下标就是maxIndex的最大值,minIndex的位置就是maxIndex的最大值
            if(maxIndex==left)maxIndex=minIndex;
            swap(array,right,maxIndex);
            left++;
            right--;
        }
    }
    

2.3 堆排序

堆序详情堆排序

 //创建二叉堆
    public static void createHeap(int[] array){
        for(int parent=(array.length-1-1)/2;parent>=0;parent--){
            siftDown(array,parent,array.length);
        }
    }
    private static void siftDown(int[] array,int parent,int size) {
        int child=2*parent+1;
        while(child<size){
            if(child+1<size&&array[child]<array[child+1]){
                //child是左右孩子的最大值
                child=child+1;
            }
            if(array[child]>array[parent]){
                //交换孩子与父亲
                swap(array,child,parent);
                //调整父亲节点和孩子节点
                parent=child;
                child=(2*parent)+1;
            }else{
                break;
            }
        }
    }
    //根据创建好的大跟堆,通过最后一个下标与0下标交换后缩小堆的范围,直到称为有序数组
    public static void heapSort(int[] array){
        createHeap(array);
        int end=array.length-1;
        while(end>0){
            swap(array,0,end);
            siftDown(array,0,end);
            end--;
        }
    }

三.交换排序

3.1 冒泡排序

 public static void bubbleSort(int[] array){
        for(int i=0;i<array.length-1;i++){
            boolean flag=false;//这里标记一下,每一趟中,给flag置为false,当每趟为有序后,则不进入if语句直接停止循环
            for(int j=0;j<array.length-1-i;j++){
                if(array[j]>array[j+1]){
                    swap(array,j,j+1);
                    flag=true;
                }
            }
            if(!flag){
                break;
            }
        }
    }

3.2 快速排序

3.2.1 Hoare排序

在这里插入图片描述
这里定义一个left为左,right为右,将任意左右位置两边定义一个基准值,根据基准值的大小,直到left为大于基准值数,right为小于基准值数停下,若定义左边为基准值则右边先走,同理右边为基准值左边先走

 //快速排序
    public static void quickSort(int[] array){
        //记录左起始位置和右边的结束位置进行递归
        quick(array,0,array.length-1);
    }
public static void inSert(int[] array,int left,int right){
        for(int i=left+1;i<=right;i++){
            int tmp=array[i];
            int j=i-1;
            for(;j>=left;j--){
                if(array[j]>tmp){
                    array[j+1]=array[j];
                }else {
                    break;
                }
            }
            array[j+1]=tmp;
        }
    }
    private static void quick(int[] array, int left, int right) {
        if(left>=right)return ;//说明两个相遇或者走出范围
        //当长度少时直接插入排序
        if(right-left+1<=10){
            inSert(array,left,right);
            return ;
        }
        int index = middleNum(array,left,right);
        System.out.println("index下标值:"+index);
        //用来交换left和right范围内元素且最终将首位元素与相遇值交换
        swap(array,left,index);
        int pos=partitionPointer(array,left,right);//递归
        quick(array,left,pos-1);
        quick(array,pos+1,right);
    }

    private static int partitionHoare(int[] array, int left, int right) {
        int record=left;//记录left最后交换
        int tmp=array[left];//比较大小
        while(left<right){
            while(left<right&&array[right]>=tmp){//右边找到小于tmp
                right--;
            }
            while(left<right&&array[left]<=tmp){//左边找到大于tmp
                left++;
            }
            swap(array,left,right);
        }
        //这里left与right相遇
        swap(array,record,left);
        return left;
    }
3.2.2 挖坑法
 public static void quickSort(int[] array){
        //记录左起始位置和右边的结束位置进行递归
        quick(array,0,array.length-1);
    }
    
public static void inSert(int[] array,int left,int right){
        for(int i=left+1;i<=right;i++){
            int tmp=array[i];
            int j=i-1;
            for(;j>=left;j--){
                if(array[j]>tmp){
                    array[j+1]=array[j];
                }else {
                    break;
                }
            }
            array[j+1]=tmp;
        }
    }
    private static void quick(int[] array, int left, int right) {
        if(left>=right)return ;//说明两个相遇或者走出范围
        if(right-left+1<=10){
            inSert(array,left,right);
            return ;
        }
        int index = middleNum(array,left,right);
        System.out.println("index下标值:"+index);
        //用来交换left和right范围内元素且最终将首位元素与相遇值交换
        swap(array,left,index);
        int pos=partitionPointer(array,left,right);//递归
        quick(array,left,pos-1);
        quick(array,pos+1,right);
    }
    
    private static int partitionPit(int[] array, int left, int right) {
        int record=array[left];//记录起始坑位
        while(left<right){
            while(left<right&&array[right]>=record){//右边找到小于tmp
                right--;
            }
            //说明找到小于tmp的值
            array[left]=array[right];
            while(left<right&&array[left]<=record){//左边找到大于tmp
                left++;
            }
            //说明找到大于tmp的值
            array[right]=array[left];
        }
        //这里left与right相遇后将记录的首个坑填入
        array[left]=record;
        return left;
    }
3.2.3 前后指针法
   public static void quickSort(int[] array){
        //记录左起始位置和右边的结束位置进行递归
        quick(array,0,array.length-1);
    }


public static void inSert(int[] array,int left,int right){
        for(int i=left+1;i<=right;i++){
            int tmp=array[i];
            int j=i-1;
            for(;j>=left;j--){
                if(array[j]>tmp){
                    array[j+1]=array[j];
                }else {
                    break;
                }
            }
            array[j+1]=tmp;
        }
    }
    private static void quick(int[] array, int left, int right) {
        if(left>=right)return ;//说明两个相遇或者走出范围
        if(right-left+1<=10){
            inSert(array,left,right);
            return ;
        }
        int index = middleNum(array,left,right);
        System.out.println("index下标值:"+index);
        //用来交换left和right范围内元素且最终将首位元素与相遇值交换
        swap(array,left,index);
        int pos=partitionPointer(array,left,right);//递归
        quick(array,left,pos-1);
        quick(array,pos+1,right);
    }

    private static int partitionPointer(int[] array, int left, int right) {
        //记录cur的前一项
     int Prev=left;
     int cur=left+1;
     while(cur<=right){
         //cur与起始位置比较只有小于才能进行交换且prev不为cur
         if(array[cur]<array[left]&&array[++Prev]!=array[cur]){
             swap(array,cur,Prev);
         }
         cur++;
     }
     //交换最后记录的cur的值
     swap(array,left,Prev);
     return Prev;
    }
3.4 非递归快速排序

这里非递归排序的情况下,因为每次最左边的数我们需要申请一个栈来记录其区间值,出栈由区间值一步步缩小取值的范围并进行交换,重复上述即可。

 public static void quickNor(int[] array){
      quickSortNor(array,0,array.length-1);
    }

    private static void quickSortNor(int[] array, int left, int right) {
        Stack<Integer> stack=new Stack<>();
        int pivot=partitionHoare(array,left,right);
        if(pivot>left+1){
            stack.push(left);
            stack.push(pivot-1);
        }
        if(pivot+1<right){
            stack.push(pivot+1);
            stack.push(right);
        }
        while(!stack.isEmpty()){
            right = stack.pop();
            left = stack.pop();
            pivot=partitionHoare(array,left,right);
            if(pivot>left+1){
                stack.push(left);
                stack.push(pivot-1);
            }
            if(pivot+1<right){
                stack.push(pivot+1);
                stack.push(right);
            }
        }

四.归并排序

4.1 递归归并排序

定义一个分界线mid来获取其中间值,递归左边和右边,每次进入方法进行排序
将左起始到中间值与中间值到右侧比较,创建一个数组来记录,排序后放到数组中,最后让原数组接收。

    public static void mergeSort(int[] array){
        mergeSortM(array,0,array.length-1);
    }

    private static void mergeSortM(int[] array, int left, int right) {
    //知道left和right相遇返回
        if(left>=right)return ;
        int mid=(left+right)/2;
      //以中间值作为分区,递归左边和右边
        mergeSortM(array,left,mid);
        mergeSortM(array,mid+1,right);
        //每次递归传入后进行排序
        merge(array,left,mid,right);
    }

    private static void merge(int[] array, int left, int mid, int right) {
        int[] tmpArr=new int[right-left+1];//创建一个数组接收每一次递归的数组
        int k=0;
          //记录左边的起始位置与右边起始位置
        int s1=left;
        int s2=mid+1;
        while(s1<= mid &&s2<= right){
            if(array[s1]<=array[s2]){
                tmpArr[k++]=array[s1++];
            }else{
                tmpArr[k++]=array[s2++];
            }
        }
        while(s1<= mid){
            tmpArr[k++]=array[s1++];
        }
        while(s2<= right){
            tmpArr[k++]=array[s2++];
        }
        for(int i=0;i<tmpArr.length;i++){
        //这里的left跟随着mid改变,当递归右侧时,left为mid+1
            array[i+left]=tmpArr[i];
        }
    }
}

4.2非递归归并排序

  private static void merge(int[] array, int left, int mid, int right) {
        int[] tmpArr=new int[right-left+1];//创建一个数组接收每一次递归的数组
        int k=0;
        //记录左边的起始位置与右边起始位置
        int s1=left;
        int s2=mid+1;
        while(s1<= mid &&s2<= right){
            if(array[s1]<=array[s2]){
                tmpArr[k++]=array[s1++];
            }else{
                tmpArr[k++]=array[s2++];
            }
        }
        while(s1<= mid){
            tmpArr[k++]=array[s1++];
        }
        while(s2<= right){
            tmpArr[k++]=array[s2++];
        }
        for(int i=0;i<tmpArr.length;i++){
            array[i+left]=tmpArr[i];
        }
    }
    
  public static void mergeNor(int[] array){
       int gap=1;//每组共有几个数据
        while(gap<array.length){
            for(int i=0;i<array.length;i=i+gap*2){
                int left=i;
                int mid=left+gap-1;
                int right=mid+gap;
                if(mid>=array.length)
                    mid=array.length-1;
                if(right>=array.length){
                    right=array.length-1;
                }
               merge(array,left,mid,right);
            }
            gap*=2;
        }
    }

五.计数排序

private static void sortCount(int[] array) {
        int maxVal=array[0];
        int minVal=array[0];
        for (int i = 0; i < array.length; i++) {
            if(array[i]>maxVal)maxVal=array[i];
            if(array[i]<minVal)minVal=array[i];
        }
        int len=maxVal-minVal+1;
        int[] count=new int[len];
        for(int i=0;i<array.length;i++){
            count[array[i]-minVal]++;
        }
        int index=0;
        for(int i=0;i<count.length;i++){
            while(count[i]>0){
                array[index]=i+minVal;
                index++;
                count[i]--;
            }
        }
    }

六.测试运行时间代码

  // 有序
    public static void order(int[] arr){
        for(int i=0;i<arr.length;i++){
            arr[i]=i;
        }
    }
    //逆序
     public static void reverse(int[] arr){
        for(int i=0;i<arr.length;i++){
            arr[i]= arr.length-i;
        }
    }
    //无序
    public static void disorder(int[] arr){
        Random random=new Random();
        for(int i=0;i<arr.length;i++){
            arr[i]= random.nextInt(100);
        }
    }

    //测试
    public static void testSort1(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
    long startTime=System.currentTimeMillis();//开始结束记录
        Sort.shellSort(tmpArray);
    long endTime=System.currentTimeMillis();
        System.out.println("希尔排序时间:"+(endTime-startTime));
    }

    public static void testSort2(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.inSert(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("插入排序时间:"+(endTime-startTime));
    }

    public static void testSort3(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.selectSort2(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("双向选择排序时间:"+(endTime-startTime));
    }
    public static void testSort4(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.bubbleSort(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("冒泡排序时间:"+(endTime-startTime));
    }
    public static void testSort5(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.heapSort(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("堆排序时间:"+(endTime-startTime));
    }
    public static void testSort6(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.quickSort(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("Hoare快速排序时间:"+(endTime-startTime));
    }
    public static void testSort7(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.quickSort(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("挖坑法快速排序时间:"+(endTime-startTime));
    }
    public static void testSort8(int[] arr){
        int[] tmpArray= Arrays.copyOf(arr,arr.length);
        long startTime=System.currentTimeMillis();//开始结束记录
        Sort.quickSort(tmpArray);
        long endTime=System.currentTimeMillis();
        System.out.println("前后指针法快速排序时间:"+(endTime-startTime));
    }

精彩评论(0)

0 0 举报