1、冒泡排序(Bubble Sort)

算法描述:
(1)比较相邻的元素。如果第一个比第二个大,就交换它们两个;
(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
(3)针对所有的元素重复以上的步骤,除了最后一个;
(4)重复步骤1~3,直到排序完成。

如果两个元素相等,不会再交换位置,所以冒泡排序是一种稳定排序算法。

方法一:自定义数组实现冒泡排序

package BubbleSort;

public class BubbleSort {
    public static void  bubbleSort(int [] data){
        int arrayLength = data.length;
        for (int i=1;i<arrayLength;i++){//从第i次排序
            for (int j=0;j<arrayLength-i;j++){ //从索引为j的位置开始
                if(data[j]>data[j+1]){//相邻的两个元素比较大小
                    int temp = data[j+1];//定义一个临时变量,用来交换两个元素
                    data[j+1]=data[j];
                    data[j]=temp;
                }
            }
            System.out.println("第"+i+"次排序:\n"+java.util.Arrays.toString(data));
        }
    }


    public static  void  main (String[] args){
        int[] data ={1,5,7,9,2,5,3,4,6,8};
        System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(data));

        bubbleSort(data); //调用方法

        System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(data));

    }

}

方法二:接收键盘输入的数据,实现冒泡排序

package BubbleSort;

import java.util.Scanner;

public class BubbleSort02 {
    public static void  bubbleSort(int[] data){
        int arrayLength = data.length;
        for (int i=1;i<arrayLength;i++){//从第i次排序
            for (int j=0;j<arrayLength-i;j++){ //从索引为j的位置开始
                if(data[j]>data[j+1]){//相邻的两个元素比较大小
                    int temp = data[j+1];//定义一个临时变量,用来交换两个元素
                    data[j+1]=data[j];
                    data[j]=temp;
                }
            }
            System.out.println("第"+i+"次排序:\n"+java.util.Arrays.toString(data));
        }
    }

        public static void main(String args[]){
            Scanner sc = new Scanner(System.in);
            String str = sc.next();
            String[] data = str.split(",");
            int[] array = new int[data.length];
            for(int i = 0;i<array.length;i++){
                array[i] = Integer.parseInt(data[i]);
            }
            System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));

            bubbleSort(array); //调用方法

            System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
        }

}

2、快速排序(Quick Sort)

算法描述:
使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
(1)从数列中挑出一个元素,称为“基准”(pivot);
(2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
(3)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

key值的选取可以有多种形式,例如中间数或者随机数,分别会对算法的复杂度产生不同的影响。

方法一:自定义数组实现快速排序

package QuickSort;

public class QuickSort {
    public static void quickSort(int[] data, int low, int high){
        int i,j,temp,t;
        if(low>high){
            return;
        }
        i=low;
        j=high;
        //temp就是基准位
        temp = data[low];
        System.out.println("基准位:"+temp);
        while (i<j) {
            //先看右边,依次往左递减
            while (temp<= data[j]&&i<j) {
                j--;
            }
            //再看左边,依次往右递增
            while (temp>= data[i]&&i<j) {
                i++;
            }
            //如果满足条件则交换
            if (i<j) {
                t = data[j];
                data[j] = data[i];
                data[i] = t;
            }

        }
        //最后将基准为与i和j相等位置的数字交换
        data[low] = data[i];
        data[i] = temp;
        //递归调用左半数组
        quickSort(data, low, j-1);
        //递归调用右半数组
        quickSort(data, j+1, high);
    }


    public static void main(String[] args){
        int[] array = {1,9,5,3,7,52,32,41,23,15,81,90,19};

        System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));

        quickSort(array, 0, array.length-1);

        System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
    }
}

方法二:接收键盘输入的数据,实现快速排序

package QuickSort;

import java.util.Scanner;

public class QuickSort02 {
    public static void quickSort(int[] data, int low, int high){
        int i,j,temp,t;
        if(low>high){
            return;
        }
        i=low;
        j=high;
        //temp就是基准位
        temp = data[low];
        System.out.println("基准位:"+temp);
        while (i<j) {
            //先看右边,依次往左递减
            while (temp<= data[j]&&i<j) {
                j--;
            }
            //再看左边,依次往右递增
            while (temp>= data[i]&&i<j) {
                i++;
            }
            //如果满足条件则交换
            if (i<j) {
                t = data[j];
                data[j] = data[i];
                data[i] = t;
            }

        }
        //最后将基准为与i和j相等位置的数字交换
        data[low] = data[i];
        data[i] = temp;
        //递归调用左半数组
        quickSort(data, low, j-1);
        //递归调用右半数组
        quickSort(data, j+1, high);
    }


    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        String[] data = str.split(",");
        int[] array = new int[data.length];
        for(int i = 0;i<array.length;i++){
            array[i] = Integer.parseInt(data[i]);
        }

        System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));

        quickSort(array, 0, array.length-1);

        System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
    }
}

3、归并排序(Merge Sort)

算法描述:

(1)把长度为n的输入序列分成两个长度为n/2的子序列。

(2)对这两个子序列分别采用归并排序。

(3)将两个排序好的子序列合并成一个最终的排序序列。

java面试排序 java排序算法面试题_java

3.1归并排序的流程

java面试排序 java排序算法面试题_数据结构_02

3.2合并两个有序数组的流程

java面试排序 java排序算法面试题_算法_03

3.3代码

方法一:自定义数组实现数组合并

package MergeSort;

import java.util.SortedMap;

public class MergeSort {
    public  static void mergeSort(int[] data){
        sort(data,0,data.length-1);
    }

    public static void sort(int[] arr, int left,int right){

        if(left == right){
            return;
        }
        int mid = left + ((right-left)>>1);
        sort(arr,left,mid);
        sort(arr,mid+1,right);
        merge(arr,left,mid,right);
    }

    private static void merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right-left+1];
        int i=0;
        int p1=left;
        int p2=mid+1;
        //比较左右两部分的元素,哪个小,把那个元素填入temp中
        while (p1<=mid&&p2<=right){
            temp[i++]=arr[p1]<arr[p2] ? arr[p1++] : arr[p2++];
        }
        //上面的循环退出后,把剩余的元素依次填入到temp中
        //以下两个while只有一个会执行
        while(p1<=mid){
            temp[i++] = arr[p1++];
        }

        while (p2<=right){
            temp[i++] = arr[p2++];
        }

        //把最终的排序的结果复制给原数组
        for(i=0;i<temp.length;i++){
            arr[left+i]=temp[i];
        }
    }


    public static void main(String[] args) {
        int[] data={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

        System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(data));

        mergeSort(data);

        System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(data));

    }
}

方法二:接收键盘输入的数据,实现数组合并

package MergeSort;

import java.util.Scanner;

public class MergeSort02 {
    public  static void mergeSort(int[] data){
        sort(data,0,data.length-1);
    }

    public static void sort(int[] arr, int left,int right){

        if(left == right){
            return;
        }
        int mid = left + ((right-left)>>1);
        sort(arr,left,mid);
        sort(arr,mid+1,right);
        merge(arr,left,mid,right);
    }

    private static void merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right-left+1];
        int i=0;
        int p1=left;
        int p2=mid+1;
        //比较左右两部分的元素,哪个小,把那个元素填入temp中
        while (p1<=mid&&p2<=right){
            temp[i++]=arr[p1]<arr[p2] ? arr[p1++] : arr[p2++];
        }
        //上面的循环退出后,把剩余的元素依次填入到temp中
        //以下两个while只有一个会执行
        while(p1<=mid){
            temp[i++] = arr[p1++];
        }

        while (p2<=right){
            temp[i++] = arr[p2++];
        }

        //把最终的排序的结果复制给原数组
        for(i=0;i<temp.length;i++){
            arr[left+i]=temp[i];
        }
    }


    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        String[] data = str.split(",");
        int[] array = new int[data.length];
        for(int i = 0;i<array.length;i++){
            array[i] = Integer.parseInt(data[i]);
        }

        System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));

        mergeSort(array);

        System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
    }
}

4、二分查找(Binary Search)

算法描述:
(1)二分查找也称折半查找,它是一种效率较高的查找方法,要求列表中的元素首先要进行有序排列。
(2)首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
(3)否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
(4)重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

代码:

方法一:递归实现二分查找

package BinarySearch;

public class BinarySearch {
    /**
     *二分查找时间复杂度0(1og2n);空间复杂度0(1)
     *
     *@param arr被查找的数组
     *@param left
     *@param right
     *@param findVal
     *@return 返回元素的索引
     */
    public  static int binarySearch(int[] arr ,int left,int right,int findVal){

        if (left > right){ //递归退出条件,找不到,返回-1
            return -1;
        }

        int  midIndex = (left+right)/2;

        if(findVal < arr[midIndex]){ //从右边向左边递归查找
            return  binarySearch(arr,left,midIndex,findVal);
        } else if (findVal > arr[midIndex]){ //从左边向右边递归查找
            return  binarySearch(arr,midIndex,right,findVal);
        } else{
            return  midIndex;
        }
    }

    public static void main(String[] args) {
        //数组需要是已经排序好的,二分查找主要使用在已经排序好的数组
        int[] data ={-23,-20,-17,8,12,23,40,50};
        int i = binarySearch(data,0,data.length,12);
        i++;
        System.out.println("查找到的数据位于第"+i+"个位置");
    }
}

方法二:非递归实现二分查找

package BinarySearch;

public class BinarySearch02 {

    /**
     * 非递归的二分查找
     *title:commonBinarySearch
     *@param arr
     *@param key
     *@return 关键字位置
     */
    public static int commonBinarySearch(int[] arr,int key){
        int low = 0;
        int high = arr.length - 1;
        int middle = 0;          //定义middle

        if(key < arr[low] || key > arr[high] || low > high){
            return -1;
        }

        while(low <= high){
            middle = (low + high) / 2;
            if(arr[middle] > key){
                //比关键字大则关键字在左区域
                high = middle - 1;
            }else if(arr[middle] < key){
                //比关键字小则关键字在右区域
                low = middle + 1;
            }else{
                return middle;
            }
        }

        return -1;    //最后仍然没有找到,则返回-1
    }

    public static void main(String[] args) {
        //数组需要是已经排序好的,二分查找主要使用在已经排序好的数组
        int[] data ={-23,-20,-17,8,12,23,40,50};
        int i = commonBinarySearch(data,12);
        i++;
        System.out.println("查找到的数据位于第"+i+"个位置");
    }


}

拓展需求:
当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到。

代码:

package BinarySearch;

import java.util.ArrayList;

public class BinarySearch03 {

    public static void main(String[] args) {

        int[] arr={10,20,23,26,26,2629,31,35,36};
        ArrayList list = binarySearch4(arr, 0, arr.length - 1, 26);
        System.out.println("返回值下标为:" + list);
    }

    //当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.
    public static ArrayList binarySearch4(int[] arr, int left, int right, int findVal){
        if(left > right){ //left > right 说明递归整个数组还没有找到
            return new ArrayList<Integer>();
        }

        int mid = (left + right)/2;
        int midValue = arr[mid];

        if(findVal > midValue){//向右递归
            return binarySearch4(arr,mid+1,right,findVal);
        }else if( findVal < midValue){//向左递归
            return binarySearch4(arr,mid,mid-1,findVal);
        }else {

            /*思路分析:
            1.在找到mid时,不马上返回
            2.向mid索引值的左边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
            3.向mid索引值的右边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
            4.返回ArrayList集合*/
            ArrayList<Integer> list = new ArrayList<Integer>();
            //向mid索引值的左边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
            int temp = mid -1;
            while(true){
                if(temp  < 0 || arr[temp] != findVal){
                    break;
                }
                list.add(temp);
                temp -= 1;//左移
            }
            list.add(mid);
            //向mid索引值的右边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
            temp = mid + 1;
            while(true){
                if(temp  >= arr.length || arr[temp] != findVal){
                    break;
                }
                list.add(temp);
                temp += 1;//右移
            }
            return list;
        }

    }

}