排序(图解各种排序)

本文详细介绍了插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序和归并排序这七种经典的排序算法,包括它们的图解过程、Java代码实现和性能分析。通过对这些排序算法的理解,有助于提升编程能力并优化算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.稳定性

相同的两个数据,经过排序后,其相对位置没有发生改变,我们就称该排序算法具有稳定性。

2.插入排序

插入排序的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

2.1图解过程

在这里插入图片描述

2.2代码实现

import java.util.Arrays;

public class Test0613_1 {
    //9,5,7,2,3,6,8
    public static void insertSort(int[]  arr){
        int bound=1; //待插入元素的下标
        for(;bound<arr.length;bound++){ //控制插入排序的次数
            int temp=arr[bound]; //把待插入的值放到临时变量中
            int cur=bound-1;
            for(;cur>=0;cur--){ //循环比较,插入合适的位置
                if(arr[cur]>temp){
                    arr[cur+1]=arr[cur]; //不符合升序,元素往后移
                }else {
                    break; //找到合适位置了,跳出整个循环
                }
            }
            arr[cur+1]=temp;//循环完后,待插入的元素要放到合适的位置
        }

    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        insertSort(arr);
        System.out.println("插入排序后:"+"==>"+"升序");
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

2.3性能分析

在这里插入图片描述

3.希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。(分组插排!!)

3.1图解过程

在这里插入图片描述

3.2代码实现

import java.util.Arrays;

public class Test0613_2 {
    public static void ShellSort(int[] arr){
        int gap=arr.length/2;
        while (gap>=1) {  //分组系数,直到1为止就成插入排序了
            int bound = gap;  //从分组系数位置出发
            for (; bound < arr.length; bound++) { //控制插排的次数
                int temp = arr[bound];
                int cur = bound - gap;
                for (; cur >= 0; cur -= gap) { //控制每次插排元素要放到的位置
                    if (arr[cur] > temp) {
                        arr[cur + gap] = arr[cur]; //不符合排序要求,元素往后移动
                    } else {
                        break; //找到合适的位置了
                    }
                }
                arr[cur + gap] = temp; //内层循环,每次插排元素要放的位置
            }
            gap=gap/2; //分组系数每次除2,直到为1
        }
    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        ShellSort(arr);
        System.out.println("希尔排序后:"+"==>"+"升序");
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

3.3性能分析

在这里插入图片描述

4.选择排序

每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排序的数据元素排完 。

4.1图解过程

在这里插入图片描述

4.2代码实现


import java.util.Arrays;

public class Test0613_3 {
    public static void SlecteSort(int[] arr){
        for(int bound=0;bound<arr.length;bound++){ //控制打擂台的次数
            for(int j=bound+1;j<arr.length;j++){ //和数组里其他元素一次比较
                if(arr[bound]>arr[j]){
                    int temp=arr[bound];
                    arr[bound]=arr[j];
                    arr[j]=temp;
                }
            }
        }

    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        SlecteSort(arr);
        System.out.println("选择排序后:"+"==>"+"升序");
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

4.3性能分析

在这里插入图片描述

5.堆排序

基本原理也是选择排序,只是不在使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大的数。(通过堆的性质完成排序)

5.1图解过程

在这里插入图片描述

5.2代码实现


import java.util.Arrays;

public class Test0613_4 {
    public static  void HeapSort(int[] arr){
        //1.先建堆(大堆)
        for(int i=(arr.length-1-1)/2;i>=0;i--){
            ShiftDown(arr,arr.length,i);
        }
        //大堆建成后,拿堆顶元素和最后一个元素交换,然后最后一个元素出堆,再向下调整堆
        int heapsize=arr.length; //一开始堆的大小就为数组的大小
        for(int i=0;i<arr.length;i++){
            //交换第一个堆顶元素和最后一个元素
            int temp=arr[0];
            arr[0]=arr[heapsize-1];
            arr[heapsize-1]=temp;
           //最后一个元素要出堆
            heapsize--;
            //向下调整堆
            ShiftDown(arr,heapsize,0);

        }

    }
    public static void ShiftDown(int[] arr,int size,int index){
        int parent=index;
        int child=2*parent+1; //左孩子
        while (child<size){ //左孩子节点小于堆的大小即可入堆调整
            //选出左右孩子中大的一个
            if (child + 1 < size && arr[child] <arr[child+1]) {
                child=child+1;
            }
            //父节点的值小于孩子节点的值交换
            if(arr[parent]<arr[child]){
                int temp=arr[parent];
                arr[parent]=arr[child];
                arr[child]=temp;
            }else {
                break;  //调整好了跳出循环
            }
            parent=child; //继续往下调整
            child=2*parent+1;
        }
    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        HeapSort(arr);
        System.out.println("堆排序排序后:"+"==>"+"升序");
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

5.3性能分析

在这里插入图片描述

6.冒泡排序

冒泡排序可以参考这个链接有详细介绍:https://blog.csdn.net/m0_54798309/article/details/112990346?utm_source=app&app_version=4.5.4

7.快速排序

从待排序区间选择一个数,作为基准值(pivot);Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的右边;然后对左右区间重复这样的操作,直到区间长度为1就代表有序了。

7.1图解过程

在这里插入图片描述

7.2代码实现(递归版本)


import java.util.Arrays;

public class Test0613_5 {

    public static void QuickSort(int[] arr){

        _QuickSort(arr,0,arr.length-1);
    }
    public static void _QuickSort(int[] arr,int left, int right){
        if(left>=right){
            return;
        }
        int index=partition(arr,left,right);
        //递归左边快排
        _QuickSort(arr,left,index-1);
        //递归右边快排
        _QuickSort(arr,index+1,right);
    }
    public static int partition(int[] arr,int left,int right){
        int l=left;
        int r=right;
        int var=arr[right]; //基准元素
        while (l<r){
            //若选取右边元素作为基准值,就先从左边出发。
            //从左边出发寻找一个比基准值大的元素
            while (l<r && arr[l]<=var){
                l++;
            }
            //从右边出发选择一个比基准值小的元素
            while (l<r && arr[r]>=var){
                r--;
            }
            //从左边和右边找到合适的元素后,进行交换
            int temp=arr[l];
            arr[l]=arr[r];
            arr[r]=temp;

        }
        //循环结束后,将基准值和左右指针相交处交换
        int temp=arr[l];
        arr[l]=arr[right];
        arr[right]=temp;
        return l; //返回左右指针相交点
    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        QuickSort(arr);
        System.out.println("快速排序排序后:"+"==>"+"升序");
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

7.3代码实现(非递归版本)


import java.util.Arrays;
import java.util.Stack;

public class Test0613_6 {
    public static void QuickSortByloop(int[] arr){
        Stack<Integer> stack=new Stack<>();
        stack.push(0);
        stack.push(arr.length-1);
        while (!stack.isEmpty()){
            int right=stack.pop();
            int left=stack.pop();
           if(left>=right){
               continue; //空区间或一个一个元素,就不要排序
           }
           int index=partition(arr,left,right);
            // 右侧区间: [index + 1, right]
            stack.push(index + 1);
            stack.push(right);
            // 左侧区间: [left, index - 1]
            stack.push(left);
            stack.push(index - 1);

        }

    }
    public static int partition(int[] arr,int left,int right){
        int l=left;
        int r=right;
        int var=arr[right]; //基准元素
        while (l<r){
            //若选取右边元素作为基准值,就先从左边出发。
            //从左边出发寻找一个比基准值大的元素
            while (l<r && arr[l]<=var){
                l++;
            }
            //从右边出发选择一个比基准值小的元素
            while (l<r && arr[r]>=var){
                r--;
            }
            //从左边和右边找到合适的元素后,进行交换
            int temp=arr[l];
            arr[l]=arr[r];
            arr[r]=temp;

        }
        //循环结束后,将基准值和左右指针相交处交换
        int temp=arr[l];
        arr[l]=arr[right];
        arr[right]=temp;
        return l; //返回左右指针相交点
    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        QuickSortByloop(arr);
        System.out.println("快速排序排序后:"+"==>"+"升序");
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

7.4性能分析(递归版本)

在这里插入图片描述

8.归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

8.1图解过程

在这里插入图片描述

8.2代码实现(递归版本)


import java.util.Arrays;

public class Test0614_6 {
    public static void mergeSort(int[] arr){
          _mergeSort(arr,0,arr.length);

    }
    public static void _mergeSort(int[] arr, int left, int right) {
        if(right-left<=1){ //区间长度为1了就不需要再切分了
            return;
        }
        int mid=(left+right)/2;
        //左边区间变成有序
        _mergeSort(arr,left,mid);
        //右边区间变成有序
        _mergeSort(arr,mid,right);
        //合并左右区间
        merge(arr,left,mid,right);
    }

    public static void merge(int[] arr,int left,int mid,int right){
        if(left>=right){
            return; //空的区间不需要合并
        }
        int[] temp=new int[right-left];
        int indextep=0;
        int cur1=left;
        int cur2=mid;
        while (cur1<mid && cur2<right){
            if(arr[cur1]<=arr[cur2]){
                temp[indextep]=arr[cur1];
                indextep++;
                cur1++;
            }else {
                temp[indextep]=arr[cur2];
                indextep++;
                cur2++;
            }
        }
        //左边区间有剩余,直接拷贝去零时数组
        while (cur1<mid){
            temp[indextep]=arr[cur1];
            indextep++;
            cur1++;
        }
        //若右边区间有剩余,则拷贝去数组
        while (cur2<right){
            temp[indextep]=arr[cur2];
            indextep++;
            cur2++;
        }
        //拷贝回原来的数组
        for(int i=0;i<temp.length;i++){
            arr[left+i]=temp[i];
        }
    }
    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        System.out.println("归并排序排序后:"+"==>"+"升序");
        mergeSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

8.3代码实现(非递归版本)


import java.util.Arrays;

public class Test0614_7 {
    public static void merge(int[] arr,int left,int mid,int right){
        if(left>=right){
            return; //空的区间不需要合并
        }
        int[] temp=new int[right-left];
        int indextep=0;
        int cur1=left;
        int cur2=mid;
        while (cur1<mid && cur2<right){
            if(arr[cur1]<=arr[cur2]){
                temp[indextep]=arr[cur1];
                indextep++;
                cur1++;
            }else {
                temp[indextep]=arr[cur2];
                indextep++;
                cur2++;
            }
        }
        //左边区间有剩余,直接拷贝去零时数组
        while (cur1<mid){
            temp[indextep]=arr[cur1];
            indextep++;
            cur1++;
        }
        //若右边区间有剩余,则拷贝去数组
        while (cur2<right){
            temp[indextep]=arr[cur2];
            indextep++;
            cur2++;
        }
        //拷贝回原来的数组
        for(int i=0;i<temp.length;i++){
            arr[left+i]=temp[i];
        }
    }
    public static void mergeSortByloop(int[] arr){
        int gap=1;
        for(;gap<arr.length;gap*=2){
            for(int i=0;i<arr.length;i+=2*gap){
                int left = i;  
                int mid = i + gap; 
                if (mid >= arr.length) {  //防止数组下标越界
                    mid = arr.length;
                }
                int right = i + 2 * gap; 
                if (right >= arr.length) {
                    right = arr.length;
                }
                merge(arr, left, mid, right);
            }
        }

    }

    public static void main(String[] args) {
        int[] arr={9,5,7,2,3,6,8};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));
        System.out.println("归并排序排序后:"+"==>"+"升序");
        mergeSortByloop(arr);
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述

8.3性能分析

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值