八大排序算法--JAVA语言版

本文深入讲解了冒泡排序、选择排序、快速排序、归并排序、直接插入排序、希尔排序和基数排序等常见排序算法的基本思想及其实现代码,通过实例帮助读者理解每种算法的工作原理。

  由于博主是一个学完知识就不爱复习的人,所以每次安排复习都很没劲儿,属于那种学了会,但是又记不住的人!于是乎把复习的形式换为写博客。如此,甚好。

一、冒泡排序--Bubble Sort

  (1)算法基本思想

     从第一个元素开始,依次比较两个相邻的元素,如果第 i 个元素比第 i+1 个元素大,就交换位置,直到遍历比较完最后一个元素就可以确定值最大的那个元素在数组arr[arr.length-1] 的位置上,至此第一轮比较结束。开始第二轮比较,因为第一轮比较确定了最大的元素,所以最后一个元素就不需要参与第二轮的比较,类似的,第三轮、第四轮。。。一共要比较 arr.length-1 轮。

     举个例子,请看下图讲解:

    观察冒泡排序的过程,可以得出以下规律:

      共需要比较的轮数:arr.length - 1 轮

      每轮比较的次数:arr.length - 1 - (第几轮-1) 次,即 arr.length - 1 - i 次

  (2)代码

 1 import java.util.Arrays;
 2 
 3 public class BubbleSort {
 4 
 5     public static void main(String[] args) {
 6         int[] arr = new int[] { 5, 7, 2, 9, 4 };
 7         System.out.println(Arrays.toString(arr));
 8         bubbleSort(arr);
 9         System.out.println(Arrays.toString(arr));
10     }
11 
12     public static void bubbleSort(int[] arr) {
13         // 控制比较多少轮
14         for (int i = 0; i < arr.length - 1; i++) {
15             // 控制比较次数
16             for (int j = 0; j < arr.length - 1 - i; j++) {
17                 if (arr[j] > arr[j + 1]) {
18                     int temp = arr[j];
19                     arr[j] = arr[j + 1];
20                     arr[j + 1] = temp;
21                 }
22             }
23         }
24     }
25 }

 

二、选择排序--Selection Sort

  (1)算法基本思想

     遍历从 0 - (length - 2) 位置的每一个元素,假设当前位置 i 的元素值为最小值,用 minIndex 记录当前位置;让当前位置的值与当前位置之后的所有元素进行比较,得出值最小的元素,并把其下标赋给minIndex,如果 minIndex != i,那么就交换这两个位置上的值,下一个位置以此类推。

     举个例子,请看下图讲解:

  (2)代码

 1 import java.util.Arrays;
 2 
 3 public class SelectionSort {
 4 
 5     public static void main(String[] args) {
 6         int[] arr = new int[] { 3, 4, 5, 7, 1, 2, 0, 3, 6, 8 };
 7         selectSort(arr);
 8         System.out.println(Arrays.toString(arr));
 9     }
10 
11     public static void selectSort(int[] arr) {
12         // 遍历所有的数
13         for (int i = 0; i < arr.length; i++) {
14             int minIndex = i;
15             // 把当前遍历的数和后面所有的数依次进行比较,并记录下最小的数的下标
16             for (int j = i + 1; j < arr.length; j++) {
17                 // 如果后面比较的数比记录的最小的数小
18                 if (arr[minIndex] > arr[j]) {
19                     minIndex = j; // 记录下最小的那个数的下标
20                 }
21             }
22             // 如果最小的数和当前遍历数的下标不一致,说明下标为minIndex的数比当前遍历的数更小
23             if (i != minIndex) {
24                 int temp = arr[i];
25                 arr[i] = arr[minIndex];
26                 arr[minIndex] = temp;
27             }
28         }
29     }
30 }

 

三、快速排序--Quick Sort

  (1)算法基本思想

     以序列的第一个元素作为标准数,初始化两个标记下标 i = 0, j = length - 1。从 j 开始与标准数进行比较,直到找到第一个比标准数小的数,把这个数赋值给位置 i ,然后从 i 开始与标准数进行比较,直到找到第一个比标准数大的数,把这个数赋值给位置 j,接着又从 j 开始寻找比标准数小的数。。。一直到 i == j 的时候停止寻找,把标准数赋值给位置 i ,就此完成了“一趟排序”。此时,在标准数的左边序列都是比标准数小的数,在标准数的右边序列都是比标准数大的数,分别对这两个序列再次进行“一趟排序”。不难看出,快速排序是一个递归的过程。

     举个例子,请看下图讲解:

  (2)代码

 1 import java.util.Arrays;
 2 
 3 public class QuickSort {
 4 
 5     public static void main(String[] args) {
 6         int[] arr = new int[] { 5, 7, 2, 9, 4 };
 7         quickSort(arr, 0, arr.length - 1);
 8         System.out.println(Arrays.toString(arr));
 9     }
10 
11     public static void quickSort(int[] arr, int start, int end) {
12         if (start >= end)// 递归结束的条件
13             return;
14         int standard = arr[start];//以序列的第一个元素作为标准数
15         int i = start;
16         int j = end;
17         while (i < j) { // 循环找比标准数大的数和比标准数小的数
18             while (i < j && arr[j] >= standard) {
19                 j--;
20             }
21             arr[i] = arr[j];
22             while (i < j && arr[i] <= standard) {
23                 i++;
24             }
25             arr[j] = arr[i];
26         }
27         arr[i] = standard;
28         quickSort(arr, start, i-1);//处理所有比标准数小的数字
29         quickSort(arr, i + 1, end);//处理所有比标准数大的数字
30     }
31 }

 

四、归并排序--Merge Sort

  (1)算法基本思想

     将一个序列从中间位置分为左子序列和右子序列,初始化两个标记下标 i,j 分别指向两个子序列的第一个元素。遍历两个子序列,比较 i,j 位置上的值,值小的就存入一个临时序列temp,直到两个子序列中的一个序列元素遍历完,把剩下序列所有的元素直接存入临时序列temp中,最后将临时序列中的数据替换掉原序列中的数据,确保每个子序列都是有序的。归并排序也是一个递归的过程。

     举个例子,请看下图讲解:

 

  (2)代码

 1 import java.util.*;
 2 
 3 class MergeSort {
 4     public static void main(String[] args) {
 5         int[] arr = new int[] { 5, 7, 2, 9, 4 };
 6         mergeSort(arr, 0, arr.length - 1);
 7         System.out.println(Arrays.toString(arr));
 8     }
 9 
10     public static void mergeSort(int[] arr, int start, int end) {
11         if (start == end)// 递归调用的出口
12             return;
13         int middle = (start + end) / 2;
14         mergeSort(arr, start, middle);// 处理左子序列
15         mergeSort(arr, middle + 1, end);// 处理右子序列
16         merge(arr, start, middle, end);// 归并
17     }
18 
19     public static void merge(int[] arr, int start, int middle, int end) {
20         int i = start;// 记录第一个数组中需要遍历的下标
21         int j = middle + 1;// 记录第二个数组中需要遍历的下标
22         int index = 0; // 用于记录在临时数组中存放的下标
23         int[] temp = new int[end - start + 1];// 用于存储归并后的临时数组
24         // 遍历两个数组取出小的数字,放入临时数组中
25         while (i <= middle && j <= end) {
26             if (arr[i] < arr[j]) {
27                 temp[index++] = arr[i];
28                 i++;
29             } else {
30                 temp[index++] = arr[j];
31                 j++;
32             }
33         }
34         // 处理多余的数据
35         while (i <= middle) {
36             temp[index++] = arr[i];
37             i++;
38         }
39         while (j <= end) {
40             temp[index++] = arr[j];
41             j++;
42         }
43         // 将临时数组中的数据替换掉原数组中的数据
44         for (int x = 0; x < temp.length; x++) {
45             arr[x + start] = temp[x];
46         }
47     }
48 }

 

五、直接插入排序--Straight Insertion Sort

  (1)算法基本思想

     假设序列的第一个元素是已排序好的有序序列,从序列的第二个元素开始遍历,将元素与之前已排序好的序列元素逐一进行比较,如果小于就交换。交换完的序列就是新排好序的有序序列。

     举个例子,请看下图讲解:

 

  (2)代码

 1 import java.util.*;
 2 
 3 class StraightInsertionSort {
 4     public static void main(String[] args) {
 5         int[] arr = new int[] { 5, 7, 2, 9, 4 };
 6         straightInsertionSort(arr);
 7         System.out.println(Arrays.toString(arr));
 8     }
 9 
10     public static void straightInsertionSort(int[] arr) {
11         for (int i = 1; i < arr.length; i++) { // 从序列的第二个元素开始遍历
12             if (arr[i] < arr[i - 1]) { // 如果当前元素比前一个元素小,才与排序好的序列元素逐一比较
13                 for (int j = i - 1; j >= 0; j--) {
14                     if (arr[j + 1] < arr[j]) { // 若小于就交换
15                         int temp = arr[j + 1];
16                         arr[j + 1] = arr[j];
17                         arr[j] = temp;
18                     }
19                 }
20             }
21         }
22     }
23 }

 

六、希尔排序--Shell Sort

  (1)算法基本思想

     把序列按一定的步长分组,遍历所有“合法”的步长。从序列的第一个元素开始遍历所有分组,用直接插入排序将分组中的元素排序。

     举个例子,请看下图讲解:

  (2)代码

 1 import java.util.*;
 2 
 3 class ShellSort {
 4     public static void main(String[] args) {
 5         int[] arr = new int[] { 5, 7, 2, 9, 4 };
 6         shellSort(arr);
 7         System.out.println(Arrays.toString(arr));
 8     }
 9 
10     public static void shellSort(int[] arr) {
11         // 遍历所有的步长
12         for (int d = arr.length / 2; d > 0; d /= 2) {
13             // 遍历所有步长为d分组
14             for (int i = 0; i < arr.length - d; i++) {
15                 // 将分组中的元素按插入排序的方式排序
16                 for (int j = i + d; j < arr.length; j += d) {
17                     if (arr[j] < arr[j - d]) {
18                         int temp = arr[j];
19                         arr[j] = arr[j - d];
20                         arr[j - d] = temp;
21                     }
22                 }
23             }
24         }
25     }
26 }

 

七、基数排序--Radix Sort

  (1)算法基本思想

     让一个序列的每一个数的个位上的数字按从小到大进行排序,直到最高数位上的数字排序完为止。

     举个例子,请看下图讲解:

  (2)代码

 1 import java.util.*;
 2 
 3 class RadixSort {
 4     public static void main(String[] args) {
 5         int[] arr = new int[] { 23, 6, 189, 45, 9, 287, 56 };
 6         radixSort(arr);
 7         System.out.println(Arrays.toString(arr));
 8     }
 9 
10     public static void radixSort(int[] arr) {
11         int[] count = new int[10];// 记录每个“桶”里有多少个数
12         int[][] ton = new int[10][arr.length];// 初始化
13         int max = Integer.MIN_VALUE;// 记录序列中最大的数
14         // 寻找序列中最大的数
15         for (int i = 0; i < arr.length; i++) {
16             if (arr[i] > max) {
17                 max = arr[i];
18             }
19         }
20         int n = (max + "").length(); // 排序次数
21         for (int i = 0, m = 1; i < n; i++, m *= 10) {
22             // 把序列中的每一个数据放进对应的“桶”
23             for (int j = 0; j < arr.length; j++) {
24                 int ys = arr[j] / m % 10;// 数位上的数字
25                 ton[ys][count[ys]] = arr[j];
26                 count[ys]++;
27             }
28             int index = 0;
29             // 取数据
30             for (int k = 0; k < 10; k++) {
31                 if (count[k] != 0) {// 只有“桶”里有数据才取
32                     for (int l = 0; l < count[k]; l++) {
33                         arr[index++] = ton[k][l];
34                     }
35                     count[k] = 0;// 取完清零以便下次计数
36                 }
37             }
38         }
39     }
40 }

 堆排序待更。。。

转载于:https://www.cnblogs.com/crush-u-1214/p/10527574.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值