java排序算法整理

转自:https://www.cnblogs.com/0201zcr/p/4763806.html

冒泡算法:一次遍历找到剩余无序元素的最值放到最后,交换完成位移。

(时间平均复杂度:O(n2))

public static void bubbleSort(int[] numbers)
{
        int temp;
        int size = numbers.length;
        for(int i = 0 ; i < size-1; i ++)
        {
            for(int j = 0 ;j < size-1-i ; j++)
            {
                if(numbers[j] > numbers[j+1])  //交换两数位置
                {
                    temp = numbers[j];
                    numbers[j] = numbers[j+1];
                    numbers[j+1] = temp;
                }
            }
        }
}

快速排序:关键字:中数、轮循赋值、中数赋值;

(时间平均复杂度:O(nlog2n))

 public static void quickSort(int[] numbers, int low, int high) {
        if (low < high) {
            int middle = getMiddleIndex(numbers, low, high);
            quickSort(numbers, low, middle - 1);
            quickSort(numbers, middle + 1, high);
        }
        System.out.println(Arrays.toString(numbers));
    }

    public static int getMiddleIndex(int[] numbers, int low, int high) {
        int middle = numbers[low];
        while (low < high) {
            while (low < high && numbers[high] > middle)
                high--;
            numbers[low] = numbers[high];
            while (low < high && numbers[low] < middle)
                low++;
            numbers[high] = numbers[low];
        }
        numbers[low] = middle;//记得返回中数下标前给中数赋值
        return low;
    }

 选择排序:一次遍历找到剩余无序元素的最值放到最前,但不是通过交换实现位移,而是通过记录下标,最后才交换一次。

(时间平均复杂度:O(n2)) 

public static void selectSort(int[] numbers) {
        int length = numbers.length;
        int temp;
        for (int i = 0; i < length; i++) {
            int k = i;//最小值下标
            for (int j = i; j < length; j++) {
                if(numbers[k] > numbers[j])
                     k = j;
            }
            temp = numbers[k];
            numbers[k] = numbers[i];
            numbers[i] = temp;
        }
        System.out.println(Arrays.toString(numbers));
    }

插入排序:数组分两段,前面的是排好序的。后面一段,拿第一个出来,排好序的一段找到合适的位置插入。

(时间平均复杂度:O(n2)) 

public static void insertSort(int[] numbers)
    {
    int size = numbers.length;
    int temp;
    
    for(int i = 0 ; i < size ; i++)
    {
        temp = numbers[i];
        int j;
        //假如temp比前面的值小,则将前面的值后移
        for(j = i ; j > 0 ; j --)
        {
            if(numbers[j-1] > temp)
                numbers[j] = numbers[j-1];//后移
            else
                break;
        }
        numbers[j] = temp;//因为是j--出来的
    }
    System.out.println(Arrays.toString(numbers));
    }

 希尔排序:若干个插入排序得到的。当遍历到最后increment=1时,则为插入排序。

(时间平均复杂度:O(n1.3))

    public static void shellSort(int[] data) {
        int j = 0;
        int temp = 0;
        //每次将步长缩短为原来的一半
        for (int increment = data.length / 2; increment > 0; increment /= 2){
            for (int i = increment; i < data.length; i++) {
                temp = data[i];
                for (j = i; j >= increment; j -= increment) {
                    if(temp < data[j - increment]){   
                        data[j] = data[j - increment];
                    }else{
                        break;
                    }
            
                } 
                data[j] = temp;
            }
    
        }
     
    }

归并排序:两段有序子序列,分别拿出第一个元素,小的放到新有序序列中。被放元素的子序列继续拿,继续比较。

说明:当向下递归到左右序列的长度都不超过2的时候,merge之后的合并序列就是有序的,所以递归往上走都是有序的。

关键字:左右指针

(时间平均复杂度:O(nlog2n))

   public static int[] sort(int[] nums, int low, int high) {
        int mid = (low + high) / 2;
        if (low < high) {
            sort(nums, low, mid);// 左边 
            sort(nums, mid + 1, high);// 右边
            merge(nums, low, mid, high);// 左右归并
        }
        return nums;
    }
    private static void merge(int[] numbers, int low, int middle, int high) {
        int[] temp = new int[high - low + 1];
        int i = low, j = middle + 1, k = 0;//i左指针,j右指针,k新数组下标
        while (i <= middle && j <= high) //轮循把小的元素放到新数组中
            temp[k++] = numbers[i] < numbers[j] ? numbers[i++] : numbers[j++];
        while (i <= middle)// 把左边剩余的数移入数组
            temp[k++] = numbers[i++];
        while (j <= high)// 把右边剩余的数移入数组
            temp[k++] = numbers[j++];
        System.arraycopy(temp, 0, numbers, low, temp.length);// 把新数组中的数覆盖numbers数组
    }

堆排序:把数组的元素看成二叉树上的结点。从最后一个非叶子节点开始,每次比较并交换后,父节点会比其子节点的值大。这样一轮循环后,最大值肯定不在最后下面一层。以此类推,最大值会跑到最上面(根节点)。然后把最大值(index=0)和数组最后一个交换,并把除了最大值的数组当做新数组,继续上述步骤。

(时间平均复杂度:O(nlog2n))

public static void main(String[] args) {
        int[] a = {2, 53, 25, 78, 9, 87, 47, 1, 28, 81, 19, 77};
        int arrayLength=a.length;
        //循环建堆
        for(int i=0;i<arrayLength-1;i++){
            //建堆
            buildMaxHeap(a,arrayLength-1-i);
            //交换堆顶和最后一个元素
            swap(a,0,arrayLength-1-i);
            System.out.println(Arrays.toString(a));
        }
    }

    //对data数组从0到lastIndex建大顶堆
    public static void buildMaxHeap(int[] data, int lastIndex){
        //从lastIndex处节点(最后一个节点)的父节点开始
        for(int i=(lastIndex-1)/2;i>=0;i--){
            //k保存正在判断的节点
            int k=i;
            //如果当前k节点的子节点存在
            while(k*2+1<=lastIndex){
                //k节点的左子节点的索引
                int biggerIndex=2*k+1;
                //如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
                if(biggerIndex<lastIndex){
                    //若果右子节点的值较大
                    if(data[biggerIndex]<data[biggerIndex+1]){
                        //biggerIndex总是记录较大子节点的索引
                        biggerIndex++;
                    }
                }
                //如果k节点的值小于其较大的子节点的值
                if(data[k]<data[biggerIndex]){
                    //交换他们
                    swap(data,k,biggerIndex);
                    //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
                    k=biggerIndex;
                }else{
                    break;
                }
            }
        }
    }
    //交换
    private static void swap(int[] data, int i, int j) {
        int tmp=data[i];
        data[i]=data[j];
        data[j]=tmp;
    }
发布了78 篇原创文章 · 获赞 131 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/river66/article/details/92653903