比较类排序算法---java版

冒泡排序(交换排序)

描述

冒泡排序是一种简单的比较类排序算法。排序的时候重复的走访过要排序的数列,一次比较两个元素,如果他们的顺序错误,那么就交换回来,走访过一遍后再来一遍,直到数列有序。

具体划分为四步:
1–比较相邻的元素,如果第一个比第二个大,交换
2–从头至尾的重复1的步骤,这样最后一个元素就是最大的
3–针对所有的元素重复以上的步骤,除了最后一个。
4–重复1到3步骤直到完成。
在这里插入图片描述

代码

public class BubbleSort {
    public static void main(String[] args) {
        Random random = new Random();
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i, random.nextInt(1000));
        }
        System.out.println(list);
        bubbleSort(list);
        System.out.println(list);

    }
    public static List<Integer> bubbleSort(List<Integer> list){
        int size = list.size();
        for (int i = 0; i < size - 1; i++) {
            for (int j = 0; j < size-1-i; j++) {
                if (list.get(j)>list.get(j+1)){
                    int temp = list.get(j);
                    list.set(j,list.get(j+1));
                    list.set(j+1,temp);
                }
            }
        }
        return list;
    }
}
public class BubbleSort {
    public static void main(String[] args) {
        int[] nums = new int[]{1,5,6,347,23,3,7,23,85};
        bubbleSort(nums);
        for (int i=0;i<nums.length;i++) {
            System.out.print(nums[i]+"  ");
        }

    }
    public static int[] bubbleSort(int[] nums){
        int length = nums.length;
        for (int i = 0; i < length - 1; i++) {
            for (int j = 0; j < length - 1 - i; j++) {
                if (nums[j]>nums[j+1]){
                    int temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
        }
        return nums;
    }
}

时间复杂度和空间复杂度

时间复杂度,最坏 O ( n 2 ) O(n^2) O(n2),最好 O ( n ) O(n) O(n);空间复杂度 O ( 1 ) O(1) O(1)。稳定的排序算法。

快速排序(交换排序)

描述

快排通过一趟排序将待排序记录分成两部分,其中一部分比另一部分全都要小,再递归进行排序,最终有序。
具体来说:
1. 从数组中选出一个基准元素-pivot和left、right;
2. 经过一次排序,把比pivot大的都放在pivot右边,比他小的放在pivot左边。(第一次从最右边往左开始找right–,只要遇到了一个比pivot小的数,就把这个数和left交换;然后从最左边开始找left++,只要遇到比pivot大的数就和right交换)
3. 递归的进行1和2步骤,直到所有元素都有序。

代码:

public class QuickSort {

    public static void main(String[] args) {
        int[] nums = {1,32,6,2,67,8,45,87,89,32,4,56,3};
        quickSort(nums,0,nums.length-1);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }
    }
    public static void quickSort(int[] nums,int left,int right){
        if (left>=right) return;
        int l = left, r = right;
        int pivot = nums[left];
        while (l<r){
            //从右向左找第一个比pivot小的值
            while (l<r && nums[r]>=pivot) r--;
            if (l<r){
                nums[l] = nums[r];
                l++;
            }
            //从左边找第一个比pivot大的值
            while (l<r && nums[l]<=pivot) l++;
            if (l<r){
                nums[r] = nums[l];
                r--;
            }
        }
        //最后把pivot填入坑中
        nums[l] = pivot;
        quickSort(nums,left,l-1);
        quickSort(nums,r+1,right);
    }
}

时间和空间复杂度

时间复杂度最好为 O ( n l o g n ) O(nlogn) O(nlogn),最差为 O ( n 2 ) O(n^2) O(n2);空间复杂度 O ( n l o g n ) O(nlogn) O(nlogn);不稳定的排序

简单插入排序

描述

选中一个有序数列,开始时为第一个元素;从前往后构造有序数列,将后面无序队列中的元素一个个放入前面有序队列中。
在这里插入图片描述

代码

public class InsertSort {
    public static void main(String[] args) {
        int[] nums = {1,32,6,35,33,87,423,3,5,8};
        insertSort(nums);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }

    }
    public static void insertSort(int[] nums){
        int length = nums.length;
        int index = 0,cur = 0;
        for (int i = 1; i < length; i++) {
            index = i - 1;
            cur = nums[i];
            while (index>=0&&nums[index]>cur){
                nums[index + 1] = nums[index];
                index--;
            }
            nums[index+1] = cur;
        }
    }
}

时间和空间复杂度

时间复杂度平均为 O ( n 2 ) O(n^2) O(n2),最好为 O ( n ) O(n) O(n);空间复杂度为 O ( 1 ) O(1) O(1);稳定的排序算法。

希尔排序(插入排序)

描述

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止

代码

public class ShellSort {
    public static void main(String[] args) {
        int[] nums = {110,98,2,4,6,32,7,32,38,5,54,62};
        shellSort(nums);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }

    }
    public static void shellSort(int[] nums){
        int index = nums.length/2;
        while (index>=1){
            for (int i = index; i < nums.length; i++) {
                int temp = nums[i];
                int j = i - index;
                while (j>=0&&nums[j]>temp){
                    nums[j+index] = nums[j];
                    j = j - index;
                }
                nums[j+index] = temp;
            }
            index = index/2;
        }
    }
}

时间和空间复杂度

时间复杂度平均 O ( n 1.3 ) O(n^{1.3}) O(n1.3),最差 O ( n 2 ) O(n^2) O(n2),最好 O ( n ) O(n) O(n);空间复杂度 O ( 1 ) O(1) O(1)。不稳定的排序算法。

简单选择排序

描述

首先在待排序序列中找到最小(大)的元素,放在排序序列的起始部位;然后再从待排序序列中继续寻找到最小(大)的元素放到已排序序列的末尾,直到所有元素都排好序。
在这里插入图片描述

代码

public class SelectionSort {
    public static void main(String[] args) {
        int[] nums = {2,5,6,1,3,64,23,56,13,75,23};
        selectionSort(nums);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }

    }

    public static void selectionSort(int[] nums){
        int length = nums.length;
        for (int i = 0; i < length; i++) {
            int sentinel = i;
            for (int j = i + 1; j < length; j++) {
                if (nums[sentinel] > nums[j]){
                    sentinel = j;
                }
            }
            int temp = nums[i];
            nums[i] = nums[sentinel];
            nums[sentinel] = temp;
        }
    }
}

时间和空间复杂度

时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( 1 ) O(1) O(1)。不稳定的排序算法

堆排序(选择排序)

描述

堆排序是利用堆这种数据结构所设计的一种排序算法。
堆的性值:每个节点的值都大于或等于其左右孩子节点的值(大根堆);每个节点的值都小于或等于其左右孩子节点的值(小根堆)。;堆是***完全二叉树***。
基本过程
1.将待排序序列构建成一个大顶堆(升序用大顶堆,降序用小顶堆)。
2.将堆顶元素和末尾元素交换,将最大元素下沉到数组末端。
3.重新调整结构,使其满足堆定义;然后继续交换堆顶元素与当前末尾元素。反复进行调整+交换,直到整个序列有序。

堆排序的性值
大顶堆: a r r [ i ] > = a r r [ 2 i + 1 ] & & a r r [ i ] > = a r r [ 2 i + 2 ] arr[i] >= arr[2i + 1] \&\& arr[i] >= arr[2i +2] arr[i]>=arr[2i+1]&&arr[i]>=arr[2i+2]
小顶堆: a r r [ i ] < = a r r [ 2 i + 1 ] & a r r [ i ] < = a r r [ 2 i + 2 ] arr[i] <= arr[2i + 1] \& arr[i] <= arr[2i +2] arr[i]<=arr[2i+1]&arr[i]<=arr[2i+2]

代码

public class HeapSort {
    public static void main(String[] args) {
        int[] arrs = {2,4,74,21,8,5,12,55,33,66,99,11};
        heapSort(arrs);
        for (int i=0;i<arrs.length;i++) {
            System.out.print(arrs[i]+" ");
        };
    }

    public static void heapSort(int[] arrs){
        //构建大根堆
        for (int i = arrs.length/2 - 1; i >= 0; i--) {
            adjustHeap(arrs,i,arrs.length);
        }
        //调整堆结构 交换堆顶元素和堆末元素
        for (int i = arrs.length - 1; i > 0; i--) {
            swap(arrs,0,i);
            adjustHeap(arrs,0,i);
        }
    }

    public static void adjustHeap(int[] arrs, int i, int len) {
        int temp = arrs[i];//初始调整的父节点---如果父节点被交换了,用temp保留最后赋值到目的节点
        for (int k = i*2 + 1; k < len; k = k*2 + 1){//从i节点的左子节点开始(2i+1)
            if (k+1 < len && arrs[k] < arrs[k+1]){//如果左子节点小于右子节点,k指向右子节点
                k++;
            }
            if (arrs[k] > temp){//如果子节点大于父节点,将子节点赋值给父节点(不是交换)
                arrs[i] = arrs[k];
                i = k;
            }else {
                break;
            }
        }
        arrs[i] = temp;
    }
    public static void swap(int[] arrs, int i, int j){
        int temp = arrs[i];
        arrs[i] = arrs[j];
        arrs[j] = temp;
    }
}

时间和空间复杂度

时间复杂度 O ( n l o n g ) O(nlong) O(nlong),空间复杂度 O ( 1 ) O(1) O(1)。不稳定的排序算法。

归并排序

思想

归并排序是分治法的一个典型应用。将待排序序列分成长度相等的两个子序列,对这个两个子序列分别采用归并排序;最后将排序好的子序列合并成一个最终的有序序列。

在这里插入图片描述

代码

public class MergeSort {
    public static void main(String[] args) {
        int[] arrs = {2,5,3,11,3,63,67,33,55,11,78};
        mergeSort(arrs);
        System.out.println(Arrays.toString(arrs));
    }
    public static void mergeSort2(int[] arrs){//迭代法
        int len = arrs.length;
        int block,start;
        int[] result = new int[len];

        for (block = 1; block < len*2; block *= 2) {
            for (start = 0; start < len; start += 2*block){
                int low = start;
                int mid = (start + block) < len ? (start + block) : len;
                int high = (start + 2*block) < len ? (start + 2*block) :len;
                //两个块的起始下标和结束下标
                int start1 = low, end1 = mid;
                int start2 = mid, end2 = high;
                //对这两个block进行归并排序
                while (start1 < end1 && start2 < end2){
                    result[low++] = arrs[start1] < arrs[start2] ? arrs[start1++] : arrs[start2++];
                }
                while (start1 < end1){
                    result[low++] = arrs[start1++];
                }
                while (start2 < end2){
                    result[low++] = arrs[start2++];
                }
            }
            int[] temp = arrs;
            arrs = result;
            result = temp;
        }
    }

    public static void mergeSort(int[] arrs){//递归
        int len = arrs.length;
        int[] res = new int[len];
        mergeSortRecursive(arrs,res,0,len - 1);
    }

    public static void mergeSortRecursive(int[] arrs,int[] result,int start,int end){
        if (start>=end) return;
        int len = end - start, mid = (len >> 1) + start;
        int start1 = start, end1 = mid;
        int start2 = mid + 1, end2 = end;
        mergeSortRecursive(arrs,result,start1,end1);
        mergeSortRecursive(arrs,result,start2,end2);
        int k = start;
        while (start1 <= end1 && start2 <= end2){
            result[k++] = arrs[start1] < arrs[start2] ? arrs[start1++] : arrs[start2++];
        }
        while (start1 <= end1){
            result[k++] = arrs[start1++];
        }
        while (start2 <= end2){
            result[k++] = arrs[start2++];
        }
        for (k = start;k<=end;k++){
            arrs[k] = result[k];
        }
    }
}

时间和空间复杂度

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度 O ( n ) O(n) O(n)。归并排序是稳定的排序算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值