几种排序算法
下面的例子介绍了4种排序方法: 冒泡排序, 选择排序, 插入排序, 快速排序
1 package date201709.date20170915; 2 3 public class SortUtil { 4 5 private static int quickSortTimes = 1; 6 7 /** 8 * 冒泡排序:<br> 9 * 两层循环,每次循环比较前后两个元素,如果他们的顺序错误就把他们交换过来,一次循环后最终会把最大的数沉到数列的末端<br> 10 * 下次循环时,上次循环沉到数列的末端的数不用再参与到本次循环中来比较<br> 11 */ 12 // 第1次排序结果: 30 59 12 46 15 83 10 59 27 91 13 // 第2次排序结果: 30 12 46 15 59 10 59 27 83 91 14 // 第3次排序结果: 12 30 15 46 10 59 27 59 83 91 15 // 第4次排序结果: 12 15 30 10 46 27 59 59 83 91 16 // 第5次排序结果: 12 15 10 30 27 46 59 59 83 91 17 // 第6次排序结果: 12 10 15 27 30 46 59 59 83 91 18 // 第7次排序结果: 10 12 15 27 30 46 59 59 83 91 19 // 第8次排序结果: 10 12 15 27 30 46 59 59 83 91 20 // 第9次排序结果: 10 12 15 27 30 46 59 59 83 91 21 public static void bubbleSort(int[] nums) { 22 int temp = 0; 23 int size = nums.length; 24 for (int i = 0; i < size - 1; i++) { 25 for (int j = 0; j < size - 1 - i; j++) { 26 if (nums[j] > nums[j + 1]) { 27 temp = nums[j]; 28 nums[j] = nums[j + 1]; 29 nums[j + 1] = temp; 30 } 31 } 32 printLog(nums, i + 1); 33 } 34 } 35 36 /** 37 * 选择排序:<br> 38 * 在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环<br> 39 */ 40 // 第1次排序结果: 10 83 59 12 46 15 91 30 59 27 41 // 第2次排序结果: 10 12 59 83 46 15 91 30 59 27 42 // 第3次排序结果: 10 12 15 83 46 59 91 30 59 27 43 // 第4次排序结果: 10 12 15 27 46 59 91 30 59 83 44 // 第5次排序结果: 10 12 15 27 30 59 91 46 59 83 45 // 第6次排序结果: 10 12 15 27 30 46 91 59 59 83 46 // 第7次排序结果: 10 12 15 27 30 46 59 91 59 83 47 // 第8次排序结果: 10 12 15 27 30 46 59 59 91 83 48 // 第9次排序结果: 10 12 15 27 30 46 59 59 83 91 49 public static void selectSort(int[] nums) { 50 int temp = 0; 51 int size = nums.length; 52 for (int i = 0; i < size - 1; i++) { 53 // 记录每一次循环最小值的位置 54 int pos = i; 55 for (int j = i + 1; j < size; j++) { 56 if (nums[pos] > nums[j]) { 57 pos = j; 58 } 59 } 60 // 最小的数与第i个位置的数交换 61 temp = nums[i]; 62 nums[i] = nums[pos]; 63 nums[pos] = temp; 64 65 printLog(nums, i + 1); 66 } 67 } 68 69 /** 70 * 插入排序<br> 71 * 每步将一个待排序的记录,按其大小插入到前面已经排序的字序列的合适位置(从后向前找到合适位置后),直到全部插入排序完为止。<br> 72 */ 73 // 第1次排序结果: 30 83 59 12 46 15 91 10 59 27 74 // 第2次排序结果: 30 59 83 12 46 15 91 10 59 27 75 // 第3次排序结果: 12 30 59 83 46 15 91 10 59 27 76 // 第4次排序结果: 12 30 46 59 83 15 91 10 59 27 77 // 第5次排序结果: 12 15 30 46 59 83 91 10 59 27 78 // 第6次排序结果: 12 15 30 46 59 83 91 10 59 27 79 // 第7次排序结果: 10 12 15 30 46 59 83 91 59 27 80 // 第8次排序结果: 10 12 15 30 46 59 59 83 91 27 81 // 第9次排序结果: 10 12 15 27 30 46 59 59 83 91 82 private static void insertSort(int[] nums) { 83 int temp = 0; 84 int size = nums.length; 85 // 从第2个元素开始,第1个元素可以认为已经被排序 86 for (int i = 1; i < size; i++) { 87 // 取出下一个元素 88 temp = nums[i]; 89 // 在已经排序的元素序列中从前向后扫描 90 for (int j = 0; j < i; j++) { 91 // 假如temp比前面的某个值小,则将这个值及之后的值后移 92 if (temp < nums[j]) { 93 for (int k = i; k > j; k--) { 94 nums[k] = nums[k - 1]; 95 } 96 nums[j] = temp; 97 break; 98 } 99 } 100 101 printLog(nums, i); 102 } 103 } 104 105 /** 106 * 快速排序:<br> 107 * 选取当前数组段的第一个数作为中轴,和最后一个比,如果比它小交换,比它大(或相等)不做任何处理<br> 108 * 交换了以后再和小的那端比,比它小不交换,比他大交换<br> 109 * 这样循环往复,一趟排序完成,左边就是比中轴小的,右边就是比中轴大的,然后再递归对左边和右边的数组排序<br> 110 */ 111 // 第1次排序结果: 27 10 15 12 30 46 91 59 59 83 112 // 第2次排序结果: 12 10 15 27 -- -- -- -- -- -- 113 // 第3次排序结果: 10 12 15 -- -- -- -- -- -- -- 114 // 第4次排序结果: -- -- -- -- -- 46 91 59 59 83 115 // 第5次排序结果: -- -- -- -- -- -- 83 59 59 91 116 // 第6次排序结果: -- -- -- -- -- -- 59 59 83 -- 117 // 第7次排序结果: -- -- -- -- -- -- 59 59 -- -- 118 public static void quickSort(int[] numbers) { 119 if (numbers.length > 1) { 120 quickSort(numbers, 0, numbers.length - 1); 121 } 122 } 123 124 private static void quickSort(int[] nums, int low, int high) { 125 if (low < high) { 126 // 选取中轴 127 int middle = getMiddle(nums, low, high); 128 printQuickSortLog(nums, low, high); 129 if (low < middle - 1) { 130 // 对低字段表进行递归排序 131 quickSort(nums, low, middle - 1); 132 } 133 if (middle + 1 < high) { 134 // 对高字段表进行递归排序 135 quickSort(nums, middle + 1, high); 136 } 137 } 138 } 139 140 private static int getMiddle(int[] nums, int low, int high) { 141 // 选取当前数组段的第一个数作为中轴 142 int temp = nums[low]; 143 while (low < high) { 144 // 比中轴大(或相等)不做任何处理(high--),直到找到比中轴小的 145 while (low < high && nums[high] >= temp) { 146 high--; 147 } 148 // 比中轴小的记录移到低端 149 nums[low] = nums[high]; 150 // 比中轴小不做任何处理(low++),直到找到比中轴大(或相等)的 151 while (low < high && nums[low] < temp) { 152 low++; 153 } 154 // 比中轴大(或相等)的记录移到高端 155 nums[high] = nums[low]; 156 } 157 // 中轴记录到尾 158 nums[low] = temp; 159 // 返回中轴的位置 160 return low; 161 } 162 163 private static void printLog(int[] nums, int times) { 164 System.out.println("第" + times + "次排序结果:\t" + formatNums(nums)); 165 } 166 167 private static void printQuickSortLog(int[] nums, int low, int high) { 168 System.out.println("第" + quickSortTimes++ + "次排序结果:\t" + formatNums(nums, low, high)); 169 } 170 171 private static String formatNums(int[] nums) { 172 return formatNums(nums, 0, nums.length - 1); 173 } 174 175 private static String formatNums(int[] nums, int low, int high) { 176 StringBuilder sb = new StringBuilder(); 177 for (int i = 0; i < low; i++) { 178 sb.append("-- "); 179 } 180 for (int i = low; i <= high; i++) { 181 sb.append(nums[i]).append(" "); 182 } 183 for (int i = high + 1; i < nums.length; i++) { 184 sb.append("-- "); 185 } 186 return sb.toString().trim(); 187 } 188 189 public static void main(String[] args) { 190 191 // 10, 12, 15, 27, 30, 46, 59, 59, 83, 91 192 int[] nums = { 30, 83, 59, 12, 46, 15, 91, 10, 59, 27 }; 193 // bubbleSort(nums); 194 // selectSort(nums); 195 // insertSort(nums); 196 // quickSort(nums); 197 } 198 }
Java实现排序的几种方式
(1) 需要排序的Bean实现Comparable<T>接口
1 package date201709.date20170915; 2 3 import java.io.Serializable; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 public class User implements Serializable, Comparable<User> { 8 9 private static final long serialVersionUID = 1L; 10 11 private Integer id; 12 13 private Integer age; 14 15 private String name; 16 17 public User(Integer id, Integer age, String name) { 18 super(); 19 this.id = id; 20 this.age = age; 21 this.name = name; 22 } 23 24 public Integer getId() { 25 return id; 26 } 27 28 public Integer getAge() { 29 return age; 30 } 31 32 public String getName() { 33 return name; 34 } 35 36 @Override 37 public String toString() { 38 return "User [id=" + id + ", age=" + age + ", name=" + name + "]"; 39 } 40 41 @SuppressWarnings("serial") 42 public static List<User> init() { 43 return new ArrayList<User>() { 44 { 45 add(new User(5, 31, "Zhang San")); 46 add(new User(2, 28, "Li Si")); 47 add(new User(3, 26, "Wang Wu")); 48 add(new User(1, 23, "Zhao Liu")); 49 add(new User(4, 26, "Liu Qi")); 50 } 51 }; 52 } 53 54 // 比较ID从而对User排序 55 @Override 56 public int compareTo(User o) { 57 return this.getId().compareTo(o.getId()); 58 } 59 }
1 package date201709.date20170915; 2 3 import java.util.Collections; 4 import java.util.List; 5 6 public class UserTest { 7 8 public static void main(String[] args) { 9 // (1) Id升序 10 List<User> userList = User.init(); 11 Collections.sort(userList); 12 printList(userList); 13 14 // (2) Id降序 15 Collections.reverse(userList); 16 printList(userList); 17 } 18 19 private static void printList(List<User> param) { 20 param.forEach(p -> { 21 System.out.println(p.toString()); 22 }); 23 } 24 }
(2) 使用内部类实现Comparator<T>接口
1 package date201709.date20170915; 2 3 import java.util.Collections; 4 import java.util.Comparator; 5 import java.util.List; 6 7 public class UserTest { 8 9 public static void main(String[] args) { 10 // (1) Age升序 11 List<User> userList = User.init(); 12 Collections.sort(userList, new AgeComparator()); 13 printList(userList); 14 15 // (2) Age降序 16 Collections.reverse(userList); 17 printList(userList); 18 } 19 20 private static void printList(List<User> param) { 21 param.forEach(p -> { 22 System.out.println(p.toString()); 23 }); 24 } 25 26 static class AgeComparator implements Comparator<User> { 27 @Override 28 public int compare(User o1, User o2) { 29 return o1.getAge().compareTo(o2.getAge()); 30 } 31 } 32 }
(3) 使用匿名内部类实现Comparator<T>接口
1 package date201709.date20170915; 2 3 import java.util.Collections; 4 import java.util.Comparator; 5 import java.util.List; 6 7 public class UserTest { 8 9 public static void main(String[] args) { 10 // (1) Age升序 11 List<User> userList = User.init(); 12 Collections.sort(userList, new Comparator<User>() { 13 @Override 14 public int compare(User o1, User o2) { 15 return o1.getAge().compareTo(o2.getAge()); 16 } 17 }); 18 printList(userList); 19 20 // (2) Age降序 21 Collections.reverse(userList); 22 printList(userList); 23 } 24 25 private static void printList(List<User> param) { 26 param.forEach(p -> { 27 System.out.println(p.toString()); 28 }); 29 } 30 }
(4) 使用lambda表达式
1 package date201709.date20170915; 2 3 import java.util.Collections; 4 import java.util.List; 5 6 public class UserTest { 7 8 public static void main(String[] args) { 9 // (1) Age升序 10 List<User> userList = User.init(); 11 Collections.sort(userList, (a, b) -> (a.getAge().compareTo(b.getAge()))); 12 printList(userList); 13 14 // (2) Age降序 15 Collections.reverse(userList); 16 printList(userList); 17 } 18 19 private static void printList(List<User> param) { 20 param.forEach(p -> { 21 System.out.println(p.toString()); 22 }); 23 } 24 }
(5) 使用stream及::表达式
1 package date201709.date20170915; 2 3 import java.util.Comparator; 4 import java.util.List; 5 import java.util.stream.Collectors; 6 7 public class UserTest { 8 9 public static void main(String[] args) { 10 // (1) Age升序 11 List<User> userList = User.init(); 12 List<User> result1 = userList.stream().sorted((a, b) -> a.getAge().compareTo(b.getAge())) 13 .collect(Collectors.toList()); 14 printList(result1); 15 16 // (2) Age降序 17 List<User> result2 = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()) 18 .collect(Collectors.toList()); 19 printList(result2); 20 } 21 22 private static void printList(List<User> param) { 23 param.forEach(p -> { 24 System.out.println(p.toString()); 25 }); 26 } 27 }