首页 > 编程语言 >十大排序算法--Java实现

十大排序算法--Java实现

时间:2024-03-19 10:02:12浏览次数:41  
标签:arr Java -- 元素 ++ int length 排序

冒泡排序 (Bubble Sort)

基本思想:

冒泡排序是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

算法步骤:

  1. 从第一个元素开始,比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

代码实现

public class BubbleSort {  
    public static void bubbleSort(int[] arr) {  
        int n = arr.length;  
        for (int i = 0; i < n - 1; i++) { // 外层循环控制排序趟数  
            for (int j = 0; j < n - i - 1; j++) { // 内层循环控制每一趟排序多少次  
                if (arr[j] > arr[j + 1]) { // 如果前一个元素比后一个元素大,则交换它们的位置  
                    int temp = arr[j];  
                    arr[j] = arr[j + 1];  
                    arr[j + 1] = temp;  
                }  
            }  
        }  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {64, 34, 25, 12, 22, 11, 90};  
        bubbleSort(arr);  
        System.out.println("Sorted array: ");  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

选择排序 (Selection Sort)

基本思想:

选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

算法步骤:

  1. 在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置。
  2. 再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。
  3. 以此类推,直到所有元素均排序完毕。

代码实现:

public class SelectionSort {  
    public static void selectionSort(int[] arr) {  
        int n = arr.length;  
        for (int i = 0; i < n - 1; i++) { // 外层循环控制选择次数  
            int minIndex = i; // 假设当前索引位置的元素是最小的  
            for (int j = i + 1; j < n; j++) { // 内层循环寻找最小元素的索引  
                if (arr[j] < arr[minIndex]) {  
                    minIndex = j; // 更新最小元素的索引  
                }  
            }  
            // 将找到的最小元素与第一个未排序位置上的元素交换  
            int temp = arr[minIndex];  
            arr[minIndex] = arr[i];  
            arr[i] = temp;  
        }  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {64, 34, 25, 12, 22, 11, 90};  
        selectionSort(arr);  
        System.out.println("Sorted array: ");  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

插入排序 (Insertion Sort)

基本思想:

插入排序的工作方式是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序。
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描。
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置。
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。
  5. 将新元素插入到该位置后。
  6. 重复步骤2~5。

代码实现:

public class InsertionSort {  
    public static void insertionSort(int[] arr) {  
        int n = arr.length;  
        for (int i = 1; i < n; ++i) { // 从第二个元素开始遍历  
            int key = arr[i]; // 取出当前元素作为key  
            int j = i - 1; // 从已排序序列的最后一个元素开始比较  
            // 将比key大的元素后移  
            while (j >= 0 && arr[j] > key) {  
                arr[j + 1] = arr[j];  
                j = j - 1;  
            }  
            arr[j + 1] = key; // 找到合适的位置插入key  
        }  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {64, 34, 25, 12, 22, 11, 90};  
        insertionSort(arr);  
        System.out.println("Sorted array: ");  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

希尔排序 (Shell Sort)

基本思想:

希尔排序是插入排序的一种更高效的改进版本,也称为缩小增量排序。希尔排序是非稳定排序算法。该算法的基本思想是:先将整个待排序的记录序列分割成为若干子序列(由相隔某个“增量”的记录组成)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

算法步骤:

  1. 选择一个增量序列 t1,t2,…,tk,其中 ti > tj,tk = 1。
  2. 按增量序列个数 k,对序列进行 k 趟排序。
    • 每趟排序,根据对应的增量 ti,将待排序列分割成 m = n/ti(n 为序列的长度)个长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
  3. 重复第2步,直到增量 ti = 1。

代码实现:

public class ShellSort {  
    public static void shellSort(int[] arr) {  
        int n = arr.length;  
        int gap = n / 2; // 初始增量  
  
        // 动态定义增量序列  
        while (gap > 0) {  
            // 对每个子序列进行插入排序  
            for (int i = gap; i < n; i++) {  
                int temp = arr[i];  
                int j = i;  
                // 插入排序  
                while (j >= gap && arr[j - gap] > temp) {  
                    arr[j] = arr[j - gap];  
                    j -= gap;  
                }  
                arr[j] = temp;  
            }  
            gap /= 2; // 缩小增量  
        }  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {9, 8, 3, 7, 5, 6, 4, 1};  
        shellSort(arr);  
        System.out.println("Sorted array: ");  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

归并排序 (Merge Sort)

基本思想:

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

算法步骤:

  1. 分解:将数组分解成两个较小的子数组,直到子数组的大小为1。
  2. 递归进行排序并合并:递归地对子数组进行排序,并将已排序的子数组合并成一个大的有序数组,直到合并为1个完整的数组。

代码实现:

public class MergeSort {  
    public static void mergeSort(int[] arr) {  
        if (arr == null || arr.length < 2) {  
            return;  
        }  
        mergeSort(arr, 0, arr.length - 1);  
    }  

    private static void mergeSort(int[] arr, int left, int right) {  
        if (left < right) {  
            int mid = left + (right - left) / 2;  
            mergeSort(arr, left, mid); // 对左半部分递归排序  
            mergeSort(arr, mid + 1, right); // 对右半部分递归排序  
            merge(arr, left, mid, right); // 合并左右两部分  
        }  
    }  

    private static void merge(int[] arr, int left, int mid, int right) {  
        int[] temp = new int[right - left + 1]; // 创建临时数组存放合并结果  
        int i = left; // 左半部分索引  
        int j = mid + 1; // 右半部分索引  
        int k = 0; // 临时数组索引  

        // 合并操作  
        while (i <= mid && j <= right) {  
            if (arr[i] <= arr[j]) {  
                temp[k++] = arr[i++];  
            } else {  
                temp[k++] = arr[j++];  
            }  
        }  
        // 将剩余的元素拷贝到临时数组中
        while (i <= mid) {
            temp[k++] = arr[i++];
        }
        while (j <= right) {
            temp[k++] = arr[j++];
        }

        // 将临时数组中的元素拷贝回原数组  
        for (int p = 0; p < temp.length; p++) {  
            arr[left + p] = temp[p];  
        }  
    }  

    public static void main(String[] args) {  
        int[] arr = {9, 8, 3, 7, 5, 6, 4, 1};  
        mergeSort(arr);  
        System.out.println("Sorted array: ");  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }
}

快速排序 (Quick Sort)

基本思想:

快速排序使用分治法的策略来把一个序列分为两个子序列,其中左边的子序列元素都不大于右边的子序列元素,然后再按此方法对子序列进行快速排序,整个序列有序。

算法步骤:

  1. 选择一个基准元素(pivot)。
  2. 通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可对这两部分记录分别继续进行排序,以达到整个序列有序。

代码实现:

public class QuickSort {  
    public static void quickSort(int[] arr, int left, int right) {  
        if (left < right) {  
            int pivotIndex = partition(arr, left, right);  
            quickSort(arr, left, pivotIndex - 1);  
            quickSort(arr, pivotIndex + 1, right);  
        }  
    }  
  
    private static int partition(int[] arr, int left, int right) {  
        int pivot = arr[right]; // 选择最右边的元素作为基准  
        int i = left - 1; // 小于基准的元素的索引  
        for (int j = left; j < right; j++) {  
            if (arr[j] <= pivot) {  
                i++;  
                // 交换 arr[i] 和 arr[j]  
                int temp = arr[i];  
                arr[i] = arr[j];  
                arr[j] = temp;  
            }  
        }  
        // 将基准元素放到正确的位置  
        int temp = arr[i + 1];  
        arr[i + 1] = arr[right];  
        arr[right] = temp;  
        return i + 1;  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {9, 8, 3, 7, 5, 6, 4, 1};  
        quickSort(arr, 0, arr.length - 1);  
        System.out.println("Sorted array: ");  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

堆排序 (Heap Sort)

基本思想:

堆排序是一种树形选择排序,是对直接选择排序的有效改进。堆排序的基本思想是将待排序的序列构造成一个大顶堆或小顶堆,此时整个序列的最大值(或最小值)就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个序列重新构造成一个堆,这样会得到n个元素中的次大值。如此反复执行,便能得到一个有序序列了。

算法步骤:

  1. 建堆:将无序序列构造成一个大顶堆(或小顶堆)。
  2. 堆调整排序
    • 将堆顶元素与末尾元素进行交换,此时末尾就为最大值。
    • 将剩余n-1个序列重新构造成一个堆。
    • 重复上述步骤,直到整个序列有序。

代码实现:

public class HeapSort {  
    public static void heapSort(int[] arr) {  
        int n = arr.length;  
          
        // 建堆  
        for (int i = n / 2 - 1; i >= 0; i--) {  
            adjustHeap(arr, i, n);  
        }  
          
        // 堆调整排序  
        for (int i = n - 1; i > 0; i--) {  
            // 交换堆顶元素和当前未排序序列的最后一个元素  
            swap(arr, 0, i);  
            // 重新调整堆  
            adjustHeap(arr, 0, i);  
        }  
    }  
  
    private static void adjustHeap(int[] arr, int i, int length) {  
        int temp = arr[i];  
        for (int k = 2 * i + 1; k < length; k = k * 2 + 1) {  
            if (k + 1 < length && arr[k] < arr[k + 1]) {  
                k++;  
            }  
            if (arr[k] > temp) {  
                arr[i] = arr[k];  
                i = k;  
            } else {  
                break;  
            }  
        }  
        arr[i] = temp;  
    }  
  
    private static void swap(int[] arr, int i, int j) {  
        int temp = arr[i];  
        arr[i] = arr[j];  
        arr[j] = temp;  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {4, 10, 3, 5, 1};  
        heapSort(arr);  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

计数排序 (Counting Sort)

基本思想:

计数排序是一种非基于比较的排序算法,适用于一定范围内的整数排序。通过统计每个元素出现的次数,将元素放到正确的位置上。

算法步骤:

  1. 找出待排序的数组中最大和最小的元素。
  2. 统计数组中每个值为i的元素出现的次数,存入数组C的第i项。
  3. 对C进行累加操作,使C[i]现在包含实际小于或等于i的元素的数量。
  4. 反向遍历原始数组,将每个元素arr[i]放到输出数组的第C[arr[i]]项,每放一个元素就将C[arr[i]]减1。

代码实现:

public class CountingSort {  
    public static void countingSort(int[] arr) {  
        if (arr == null || arr.length == 0) {  
            return;  
        }  
  
        // 找到数组中的最大值和最小值  
        int max = arr[0];  
        int min = arr[0];  
        for (int i = 1; i < arr.length; i++) {  
            if (arr[i] > max) {  
                max = arr[i];  
            }  
            if (arr[i] < min) {  
                min = arr[i];  
            }  
        }  
  
        // 初始化计数数组  
        int[] count = new int[max - min + 1];  
        for (int i = 0; i < arr.length; i++) {  
            count[arr[i] - min]++;  
        }  
  
        // 累加计数数组  
        for (int i = 1; i < count.length; i++) {  
            count[i] += count[i - 1];  
        }  
  
        // 排序  
        int[] sortedArr = new int[arr.length];  
        for (int i = arr.length - 1; i >= 0; i--) {  
            sortedArr[count[arr[i] - min] - 1] = arr[i];  
            count[arr[i] - min]--;  
        }  
  
        // 将排序后的数组拷贝回原数组  
        System.arraycopy(sortedArr, 0, arr, 0, arr.length);  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {4, 2, 2, 8, 3, 3, 1};  
        countingSort(arr);  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

桶排序 (Bucket Sort)

基本思想:

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:

  1. 首先要使得数据分散得尽可能均匀;
  2. 对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

算法步骤:

  1. 设置一个定量的数组当作空桶子。
  2. 寻访序列,并且把项目一个一个放到对应的桶子去。
  3. 对每个不是空的桶子进行排序。
  4. 从不是空的桶子里把项目再放回原来的序列中。

代码实现:

import java.util.ArrayList;  
import java.util.Collections;  
import java.util.List;  
  
public class BucketSort {  
    public static void bucketSort(int[] arr) {  
        if (arr == null || arr.length == 0) {  
            return;  
        }  
  
        // 找到数组中的最大值和最小值  
        int min = arr[0];  
        int max = arr[0];  
        for (int i = 1; i < arr.length; i++) {  
            if (arr[i] < min) {  
                min = arr[i];  
            } else if (arr[i] > max) {  
                max = arr[i];  
            }  
        }  
  
        // 计算桶的数量  
        int bucketSize = (max - min) / arr.length + 1;  
        List<List<Integer>> buckets = new ArrayList<>(arr.length);  
        for (int i = 0; i < arr.length; i++) {  
            buckets.add(new ArrayList<>());  
        }  
  
        // 将元素放入桶中  
        for (int i = 0; i < arr.length; i++) {  
            int index = (int) ((arr[i] - min) / bucketSize);  
            buckets.get(index).add(arr[i]);  
        }  
  
        // 对每个桶中的元素进行排序  
        int k = 0;  
        for (List<Integer> bucket : buckets) {  
            if (!bucket.isEmpty()) {  
                Collections.sort(bucket);  
                for (int num : bucket) {  
                    arr[k++] = num;  
                }  
            }  
        }  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {64, 34, 25, 12, 22, 11, 90};  
        bucketSort(arr);  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

基数排序(Radix Sort)

基本思想

一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。这里,我们假设要排序的整数都是非负整数。基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。

算法步骤:

  1. 找到最大数:首先找到待排序数组中的最大数,确定位数。
  2. 从最低位开始排序:对每一位使用稳定的排序算法进行排序,例如计数排序。
  3. 依次进行更高位的排序:从最低位开始,依次对每一位进行排序,直到最高位。
  4. 收集排序结果:每次排序后,根据排序的键值收集排序结果。

代码实现:

public class RadixSort {  
      
    // 获取最大数的位数  
    private static int getMaxDigit(int[] arr) {  
        int max = arr[0];  
        for (int num : arr) {  
            max = Math.max(max, num);  
        }  
        int digit = 0;  
        while (max != 0) {  
            max /= 10;  
            digit++;  
        }  
        return digit;  
    }  
  
    // 基数排序函数  
    public static void radixSort(int[] arr) {  
        if (arr == null || arr.length == 0) {  
            return;  
        }  
          
        // 获取最大位数  
        int maxDigit = getMaxDigit(arr);  
          
        // 初始化桶  
        int[] bucket = new int[arr.length];  
        int[] count = new int[10]; // 假设我们排序的是十进制数  
          
        // 从最低位开始排序  
        for (int i = 0; i < maxDigit; i++) {  
            // 计数排序  
            for (int j = 0; j < arr.length; j++) {  
                int digit = (arr[j] / (int) Math.pow(10, i)) % 10;  
                count[digit]++;  
            }  
              
            // 计算前缀和  
            for (int j = 1; j < count.length; j++) {  
                count[j] += count[j - 1];  
            }  
              
            // 收集结果  
            for (int j = arr.length - 1; j >= 0; j--) {  
                int digit = (arr[j] / (int) Math.pow(10, i)) % 10;  
                bucket[count[digit] - 1] = arr[j];  
                count[digit]--;  
            }  
              
            // 复制回原数组  
            for (int j = 0; j < arr.length; j++) {  
                arr[j] = bucket[j];  
            }  
              
            // 重置count数组  
            for (int j = 0; j < count.length; j++) {  
                count[j] = 0;  
            }  
        }  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};  
        radixSort(arr);  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

标签:arr,Java,--,元素,++,int,length,排序
From: https://blog.csdn.net/weixin_53451443/article/details/136832018

相关文章

  • C#,人工智能,机器学习,聚类算法,训练数据集生成算法、软件与源代码
    摘要:本文简述了人工智能的重要分支——机器学习的核心算法之一——聚类算法,并用C#实现了一套完全交互式的、可由用户自由发挥的,适用于聚类算法的训练数据集生成软件——Clustering。用户使用鼠标左键(拖动)即可生成任意形状,任意维度,任意簇数及各种数据范围的训练数据集,同时也可以......
  • 【matlab】如何批量修改图片命名
    【matlab】如何批量修改图片命名(●’◡’●)先赞后看养成习惯......
  • Tauri 使用
    首先确保安装了Cargo:https://www.rust-lang.org/tools/install官网:https://tauri.app/v1/guides/getting-started/setup安装:cargoinstallcreate-tauri-app--locked创建项目,后面根据你的需要选择对应的选项:cargocreate-tauri-app......
  • SpringBoot集成MybatisPlus
    创建一个基于SpringBoot集成MybatisPlus的示例项目是一个相对直接且实用的过程,它结合了SpringBoot的自动配置特性与MybatisPlus的增强功能,使得数据库操作变得更为简便和高效。下面是一个简单的步骤说明和代码示例,帮助你快速搭建一个SpringBoot集成MybatisPlus的Demo项......
  • 数据库巡检
    【文章转载于https://cloud.tencent.com/developer/article/2390515】数据库巡检基于时间纬度数据库巡检可以分为日常巡检,基于我们积累的运维经验和故障经验,形成数据库层的监控,比如主键溢出,备份有效性验证,配置参数和内存中运行的参数是否一致,主备参数是否一致等等节前巡检,主......
  • C#,深度好文,精致好码,文本对比(Text Compare)算法与源代码
    VladimirI.Levenshtein一、文本对比的列文斯坦距离(编辑距离)算法在日常应用中,文本比较是一个比较常见的问题。文本比较算法也是一个老生常谈的话题。文本比较的核心就是比较两个给定的文本(可以是字节流等)之间的差异。目前,主流的比较文本之间的差异主要有两大类。一类是基......
  • matinal:SAP FICO会计凭证如何实现自动拆分
    ......
  • GPT实战系列-LangChain的Prompt提示模版构建
    GPT实战系列-LangChain的Prompt提示模版构建LangChainGPT实战系列-LangChain如何构建基通义千问的多工具链GPT实战系列-构建多参数的自定义LangChain工具GPT实战系列-通过Basetool构建自定义LangChain工具方法GPT实战系列-一种构建LangChain自定义Tool工具的简单方法G......
  • 其他漏洞
    漏洞介绍用友GRP_U8bx_historyDataCheck.jsp存在sql注入,攻击者可利用该漏洞执行任意SQL语句,如查询数据、下载数据、写入Webshell、执行系统命令以及绕过登录限制fofa:app="用友-GRP-U8"用友NCaccept.jsp处存在任意文件上传漏洞fofa:app="用友-UFIDA-NC"pocPOST/aim/equipma......
  • 303. 区域和检索 - 数组不可变
    目录题目前缀和题目给定一个整数数组nums,处理以下类型的多个查询:计算索引left和right(包含left和right)之间的nums元素的和,其中left<=right实现NumArray类:NumArray(int[]nums)使用数组nums初始化对象intsumRange(inti,intj)返回数组nums中索引......