数据结构之排序算法(归并、冒泡、选择、插入、快速、希尔、基数排序)

本文详细介绍了八种常见的排序算法,包括归并排序、冒泡排序、选择排序、插入排序、希尔排序、快速排序以及基数排序。每种算法都配合了代码实现,便于理解和学习。这些排序算法在计算机科学中有着广泛的应用,对于提升程序效率至关重要。
摘要由CSDN通过智能技术生成

 前言

八大排序算法:

直接插入排序、希尔排序、简单选择排序、堆排序、冒泡排序、快速排序、归并排序、基数排序

一、归并排序

    1)基本介绍

     

   2)基本思想

     

3)代码实现

public class MergeSort {
    public static void main(String[] args) {
        int arr[] = {8, 4, 5, 3, 2, 7, 6, 1};
        int temp[] = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
        System.out.println(Arrays.toString(arr));
    }

    //分+合
    public static void mergeSort(int[] arr,int left,int right,int[] temp){
        if (left < right){
            int mid = (left + right)/2;
            //向左递归进行分解
            mergeSort(arr, left, mid, temp);
            //向右递归分解
            mergeSort(arr, mid + 1,right, temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }

    //合并的方法
    /**
     *
     * @param arr 需要排序的数组
     * @param left 左边有序序列的初始索引
     * @param mid 中间索引
     * @param right 右边有序序列索引
     * @param temp 中转数组
     */
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;
        int j = mid + 1;
        int t = 0;//中转数组的下标
        //步骤1.
        //把左右两边的有序序列数按规则填充到中转数组
        //直到有一边序列都填完了
        while (i <= mid && j <= right){//进行步骤1的条件
            //左边的小于右边的,就将左边这个小的填到temp
            //然后t,i后移
            if(arr[i] < arr[j]){
                temp[t] = arr[i];
                t++;
                i++;
            }else {//否则右边这个小的数填到temp,然后t,j后移
                temp[t] = arr[j];
                t++;
                j++;
            }
        }
        //步骤2
        //把有剩余的有序序列依次填到temp
        while (i <= mid){//说明左边有剩余
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }
        while (j <= right){
            temp[t] = arr[j];
            t++;
            j++;
        }
        //步骤3
        //把temp复制到原来的数组arr
        t = 0;
        int tempLeft = left;
        while (tempLeft <= right){
            arr[tempLeft] = temp[t];
            t++;
            tempLeft++;
        }
    }
}

二、冒泡排序

     1)基本介绍

  2)代码实现

  public static void bubbleSort(int arr[]){
        int temp = 0;
        boolean flag = false;//标识符,判断是否进行过交换,用来让排序提前结束
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    flag = true;
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            //System.out.println("第" + (i+1) + "趟排序后");
            //System.out.println(Arrays.toString(arr));

            if (!flag){
                break;
            }else {
                flag = false;
            }
        }
    }

 三、选择排序

      1)基本介绍

     2)基本思想

    3) 思路

 4)代码实现

 public static void selectSort(int[] arr) {

        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;//假定最小值的索引
            int min = arr[i];//假定一个最小值
            for (int j = i + 1; j < arr.length; j++) {
                if (min > arr[j]) {//说明假定的最小值,并不是最小;若从大到小,则改成<
                    min = arr[j];//重置
                    minIndex = j;
                }
            }
            //将最小值放在arr[0],即交换
            if (minIndex != i) {//在原位置的不进行交换
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
            //System.out.println("第" + (i + 1) + "轮交换");
            //System.out.println(Arrays.toString(arr));
        }
    }

    四、插入排序

           1)基本介绍

        2)思路图分析

          3)代码实现

 public static void insertSort(int[] arr){

        for (int i = 0; i < arr.length; i++) {
            //定义无序表里的那个待插入的数
            int insertVal = arr[i];
            int insertIndex = i - 1;//arr[i]的前面的数的下标,有序表里的数
            //给insertVal找插入位置
            while (insertIndex >= 0 && insertVal < arr[insertIndex]){
                //insertVal < arr[insertIndex]说明不能插在这,还得往有序表前找
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }
            //当退出while后,说明位置找到,insertIndex+1
            arr[insertIndex + 1] = insertVal;

            System.out.println("第" +  i + "轮插入");
            System.out.println(Arrays.toString(arr));
        }
    }

五、希尔排序

       1)基本介绍

2)思路分析图                                                                                                              

                                                                                                                                  

      4)代码实现,希尔排序可分为交换法和移动法

 //交换
    public static void shellSort01(int[] arr){
        int temp = 0;
        int count = 0;
        //分组
        for (int gap = arr.length / 2; gap > 0; gap /= 2){
            for (int i = gap; i < arr.length; i++){
                //遍历各组中所有的元素,本例子共5组,每组两个元素
                //步长为5,即十个数分成五组,每组中的两个元素相隔5个步数
                for (int j = i - gap; j >= 0; j -= gap){
                    //如果当前元素大于同组中的另一个元素,则交换
                    if (arr[j] > arr[j + gap]){
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                }
            }
            System.out.println("希尔排序第" + (++count) + "轮后" + Arrays.toString(arr));
        }
    }


 //移动,快得多
    public static void shellSort02(int[] arr){
        for (int gap = arr.length / 2; gap > 0; gap /= 2){
            //从第gap个元素,逐个对其所在的组进行直接插入排序
            for (int i = gap; i < arr.length; i++){
                int j = i;
                int temp = arr[j];
                if (arr[j] < arr[j - gap]){
                    while (j - gap >= 0 && temp < arr[j - gap]){
                        //移动
                        arr[j] = arr[j - gap];
                        j -= gap;
                    }
                    //退出while循环,找到temp插入的位置
                    arr[j] = temp;
                }
            }
        }
    }

六、快速排序

     1)基本介绍

    2)思路图分析

3)代码实现

 public static void quickShort(int[] arr,int left,int right){
        int l = left;//左下标
        int r = right;//右下标
        int pivot = arr[(left + right)/2];//中值
        int temp = 0;
        //while 让大于pivot到右边,小于到左边
        while (l < r){
            //在pivot的左边找到大于等于pivot的值,退出
            while (arr[l] < pivot){
                l += 1;
            }
            //在pivot的右边找到小于等于pivot的值,退出
            while (arr[r] > pivot){
                r -= 1;
            }
            //如果l>=r,说明排好了
            if (l >= r){
                break;
            }
            //交换
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            //如果交换后,arr[l]==pivot,则r--,前移
            if (arr[l] == pivot){
                r--;
            }
            //如果交换后,arr[r]==pivot,则l++,后移
            if (arr[r] == pivot){
                l++;
            }
        }
        //如果l==r,必须l++,r--,否则栈溢出
        if (l == r){
            l += 1;
            r -= 1;
        }
        //向左递归
        if (left < r){
            quickShort(arr,left,r);
        }
        //向右递归
        if (right > l){
            quickShort(arr,l,right);
        }
    }

 七、基数排序

       1)基本介绍

     2)基本思想

    3)思路分析图,以下图中的arr为例,需三轮排序

第一轮排序,定义一个二位数组,表示十个桶。先按个位,将每个元素放到对应的桶(一维数组)中,比如53的个位是3,就放到下标为3的桶中,然后按桶的顺序,桶中元素的顺序,将各元素依次放回到原来数组中

第二轮 ,按十位,将每个元素放到对应的桶(一维数组)中,比如53的十位是5,就放到下标为5的桶中,如果元素是4,十位就补0,放到下标为0的桶中,然后按桶的顺序,桶中元素的顺序,将各元素依次放回到原来数组中

第三轮,按百位,同上两轮。 

     4)代码实现

 public static void radixSort(int arr[]){
        //1.得到数组中最大数的位数
        int max = arr[0];
        for (int i = 1; i < arr.length; i++){
            if (arr[i] > max){
                max = arr[i];
            }
        }
        //得到最大数是几位数
        int maxLength = (max + " ").length();

        //定义一个二维数组,表示十个桶,每个桶就是一个一维数组
        //每个桶(一维数组)的大小定位arr.length,防止数据溢出,空间换时间
        int[][] bucket = new int[10][arr.length];
        //定义一个一维数组来记录各个桶的每次放入数据的个数
        //bucketElementCounts[0],记录的就是bucket[0]桶的放入数据的个数
        int[] bucketElementCounts = new int[10];

        for (int i = 0, n = 1; i < maxLength; i++, n *= 10){
            //每个元素的位数进行排序,个,十,百,n代表位数
            for (int j = 0; j < arr.length; j++){
                //1.取出每个元素的对应位数
                int individual = arr[j] / n % 10;
                //2.放入到对应的桶
                bucket[individual][bucketElementCounts[individual]] = arr[j];
                bucketElementCounts[individual]++;
            }
            //3.将桶中的数据放到原数组
            //按照桶的顺序(一维数组的下标)依次取出数据,放到原来数组
            int index = 0;
            //遍历每个桶,取出数据放到原来数组
            for (int k = 0; k < bucketElementCounts.length; k++){
                //判断桶里有没有数据
                if (bucketElementCounts[k] != 0){
                    //这第k个桶有数据,全取出来,放arr里
                    for (int l = 0; l < bucketElementCounts[k]; l++){
                        arr[index++] = bucket[k][l];
                    }
                }
                //第i+1轮后,桶要清零
                bucketElementCounts[k] = 0;
            }
            System.out.println("第"+(i+1)+"轮排序后,arr=" + Arrays.toString(arr));
        }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值