由于博主是一个学完知识就不爱复习的人,所以每次安排复习都很没劲儿,属于那种学了会,但是又记不住的人!于是乎把复习的形式换为写博客。如此,甚好。
一、冒泡排序--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 }
堆排序待更。。。
本文深入讲解了冒泡排序、选择排序、快速排序、归并排序、直接插入排序、希尔排序和基数排序等常见排序算法的基本思想及其实现代码,通过实例帮助读者理解每种算法的工作原理。
2139

被折叠的 条评论
为什么被折叠?



