java实现堆排序、冒泡排序、快速排序(递归和非递归)、归并排序(递归与非递归)

堆排序

和直接选择排序很像,每次去一个最大值,放到数组的最后。
实现:1. 先针对整个数组建堆;2.循环取堆顶最大值,放到最后面
3调整堆
时间复杂度O(NlogN)
空间复杂度O(1)
不稳定

public static void heapSort(int[] array) {
        createHeap(array);  //1.创建堆
        for (int i = 0; i < array.length; i++) {
            //2.循环取最大
            //区间分成两部分,待排序区间[0,array.length-i)
            //               已排序区间[array.length-i,array.length)
            swap(array,0,array.length-i-1);
            shiftDown(array,array.length-i-1,0);
        }
    }
    private static void createHeap(int[] array) {
        //从最后一个非叶子结点,开始出发,从后往前向下调整
        for (int i = (array.length-1-1)/2; i >= 0; i--) {
            shiftDown(array,array.length,i);
        }
    }
    //下沉调整
    private static void shiftDown(int[] array, int size, int index) {
        int parent = index;
        int child = 2 * parent + 1;
        while (child < size) {
            if(child + 1 <size && array[child + 1] >array[child]) {
                child = child + 1;
            }
            if(array[child] > array[parent]) {
                swap(array,parent,child);
            } else {
                break;
            }
            parent = child;
            child = 2 * parent + 1;
        }
    }

冒泡排序**

实现:每次找出待排序区间的最大值或最小值,相邻元素比较,从前往后比较或从后往前比较
时间复杂度O( n^2)
空间复杂度O(1)
不稳定

public static void bubbleSort(int[] array) {
        for (int bound = 0;bound < array.length; bound++) {
            for (int cur =array.length-1; cur >= bound; cur--) {
                if(array[cur-1] > array[cur]){
                    swap(array,cur-1,cur);
                }
            }
        }
    }

快速排序***

实现:先选择一个基准值
例如: 9 5 2 7 3 6 8 9 4
选最后一个元素4为基准值,从前往后找到比4大的第一个元素,从后往前找到比基准值小的第一个元素,交换这两个元素,若没有找到,就将基准值和找到的那个元素交换(重合时)
核心思路:借助递归
时间复杂度O(n^2) 平均O(NlogN)
空间复杂度O(n) 平均O(logN)

public static void quickSort(int[] array) {
        quickSortHeaper(array,0,array.length-1);
        //参数的含义表示针对数组中的那段区间进行快速排序[0,array.length-1]
    }
    private  static void quickSortHeaper(int[] array,int left,int right){
       //只有一个元素
        if (left >= right) {
            return;
        }
        int index = Partition(array,left,right);
        quickSortHeaper(array, left, index-1);
        quickSortHeaper(array, index + 1, right);
    }

    private static int Partition(int[] array,int left, int right) {
        int baseIndex = right;
        int baseValue = array[baseIndex];  //取出基准值
        while (left < right) {
            while (left < right && array[left] <= baseValue) {
                left ++;
            }
            while(left <right && array[left] >= baseValue) {
                right--;
            }
            swap(array,left,right);
        }
        swap(array,left,baseIndex);//重合位置和基准值交换
        return left;
    }

    //快速排序(非递归)
    public static void quickSortByLoop(int[] array) {
        //创建一个栈,存的是待处理区间的下标
        Stack<Integer> stack = new Stack<>();
        stack.push(array.length-1);//初始情况下待处理区间就是整个数组
        stack.push(0);
        //取栈顶元素,栈顶元素就是我们要处理的区间
        while(!stack.isEmpty()) {
            int left = stack.pop();
            int right = stack.pop();
            if(left >= right) {
                continue;
            }
            //4.对当前待处理区间进行整理
            int index = Partition(array,left,right);
                stack.push(index - 1);
                stack.push(left);
                stack.push(right);
                stack.push(index + 1);
        }
    }

快速排序的优化:
1.取基准值 :三元素取中
2.如果递归深度到达一定的层次之后,就不在继续递归,对待排区间使用其他排序方法
3.如果当前待排序区间较小,之间使用插排即可

归并排序

归并两个有序的链表,变成一个有序的链表
时间复杂度O(NlogN)
空间复杂度O(N)

//7.归并排序
    public static void mergeSort(int[] array) {
        //后两个参数表示要进行归并的区间[0,array.length)
        mergeSortHelper(array,0,array.length);
    }

    private static void mergeSortHelper(int[] array, int left, int right) {
        //空区间或只有一个元素,都不需要进行归并
        if(left == right || left > right || right - left == 1) {
            return;
        }
        int mid = (left + right) /2;
        mergeSortHelper(array,left,mid);
        mergeSortHelper(array,mid,right);
        merge(array,left,mid,right);
    }

    private static void merge(int[] array, int left, int mid, int right) {
        //创建一段临时空间辅助,长度应是两个待排序区间之和
        int length = right - left;
        int[] output = new int[length];
        int outputIndx = 0;//保存output中末尾元素的下标
        int i = left;
        int j = mid;
        while(i < mid && j < right) {
            if(array[i] <= array[j]) {
                output[outputIndx++] = array[i++];
            } else {
                output[outputIndx++] =array[j++];
            }
            //循环完后,把剩下的一方直接拷贝到output中
            while (i < mid) {
                output[outputIndx++] = array[i++];
            }
            while (j < right) {
                output[outputIndx++] = array[j++];
            }
            //最后,把output中的元素拷贝到原来的区间
            for (int k = 0; k < length; k++) {
                array[left - k] = output[k];
            }
        }
    }

    //非递归归并排序
    public static void mergeSortByLoop(int[] array) {
        for (int gap= 1; gap < array.length; gap *= 2) {
            for (int i= 0; i < array.length; i += 2 * gap) {
                int beg = i;
                int mid = i + gap;
                int end = i + 2*gap;
                if(mid > array.length) {
                    mid = array.length;
                }
                if (end > array.length) {
                    end = array.length;
                }
                merge(array,beg,mid,end);
            }
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值