1. 程式人生 > 實用技巧 >經典排序演算法

經典排序演算法

data.txt

1 8,10,211,4,128,12,5,365,9,192,7,1,3,2,6,1024,11,13,20,54

SortAlgorithm.java

  1 package io.guangsoft;
  2 
  3 import java.io.FileInputStream;
  4 import java.lang.reflect.InvocationHandler;
  5 import java.lang.reflect.Method;
  6 import java.lang.reflect.Proxy;
  7 import java.nio.ByteBuffer;
8 import java.nio.channels.FileChannel; 9 import java.util.Arrays; 10 11 public class SortAlgorithm { 12 13 //排序演算法介面 14 interface Sort { 15 //排序演算法名稱 16 String sortName(); 17 //元素大小的判斷 18 static boolean greater(Comparable x, Comparable y) { 19 return
x.compareTo(y) > 0; 20 } 21 //交換元素 22 static void swap(Comparable[] data, int i, int j) { 23 Comparable temp = data[i]; 24 data[i] = data[j]; 25 data[j] = temp; 26 } 27 //排序方法 28 Comparable[] sort(Comparable[] data);
29 } 30 31 //氣泡排序 32 static class BubbleSort implements Sort { 33 @Override 34 public String sortName() { 35 return "氣泡排序"; 36 } 37 @Override 38 public Comparable[] sort(Comparable[] data) { 39 //需要從由大到小範圍進行n-1次篩選 40 for(int i = 0; i < data.length - 1; i++) { 41 //在每次篩選的範圍內逐個比較,將最小值冒泡到範圍最左端 42 for(int j = data.length - 1; j > i; j--) { 43 if(Sort.greater(data[j - 1], data[j])) { 44 Sort.swap(data, j - 1, j); 45 } 46 } 47 } 48 return data; 49 } 50 } 51 52 //選擇排序 53 static class SelectionSort implements Sort { 54 @Override 55 public String sortName() { 56 return "選擇排序"; 57 } 58 @Override 59 public Comparable[] sort(Comparable[] data) { 60 //需要從由大到小範圍進行n-1次篩選 61 for(int i = 0; i < data.length - 1; i++) { 62 //在每次篩選的範圍內選出最小值,將最小值交換到範圍最左端 63 int minIndex = i; 64 for(int j = i + 1; j < data.length; j++) { 65 if(Sort.greater(data[minIndex], data[j])) { 66 minIndex = j; 67 } 68 } 69 Sort.swap(data, i, minIndex); 70 } 71 return data; 72 } 73 } 74 75 //插入排序 76 static class InsertionSort implements Sort { 77 @Override 78 public String sortName() { 79 return "插入排序"; 80 } 81 @Override 82 public Comparable[] sort(Comparable[] data) { 83 //需要從由小到大範圍進行n-1次篩選 84 for(int i = 1; i < data.length; i++) { 85 //在每次篩選的範圍內將新增元素插入到有序位置 86 for(int j = i; j > 0; j--) { 87 if(Sort.greater(data[j - 1], data[j])) { 88 Sort.swap(data, j - 1, j); 89 } else { 90 break; 91 } 92 } 93 } 94 return data; 95 } 96 } 97 98 //希爾排序 99 static class ShellSort implements Sort { 100 @Override 101 public String sortName() { 102 return "希爾排序"; 103 } 104 @Override 105 public Comparable[] sort(Comparable[] data) { 106 int gap = 1; 107 //確定初始增量 108 while(gap < data.length / 2) { 109 gap = 2 * gap + 1; 110 } 111 //逐步二分縮小排序增量 112 while(gap >= 1) { 113 //從中間位置開始向後逐步分組 114 for(int i = gap; i < data.length; i++) { 115 //組內進行插入排序 116 for(int j = i; j >= gap; j -= gap) { 117 if(Sort.greater(data[j - gap], data[j])) { 118 Sort.swap(data, j - gap, j); 119 } else { 120 break; 121 } 122 } 123 } 124 //縮小gap 125 gap >>>= 1; 126 } 127 return data; 128 } 129 } 130 131 //歸併排序 132 static class MergeSort implements Sort { 133 private static Comparable[] assist; 134 @Override 135 public String sortName() { 136 return "歸併排序"; 137 } 138 @Override 139 public Comparable[] sort(Comparable[] data) { 140 assist = new Comparable[data.length]; 141 int lo = 0; 142 int hi = data.length - 1; 143 sort(data, lo, hi); 144 return data; 145 } 146 //遞迴體 147 private static void sort(Comparable[] data, int lo, int hi) { 148 if(hi <= lo) return; 149 int mid = lo + (hi - lo) / 2; 150 sort(data, lo, mid); 151 sort(data, mid + 1, hi); 152 merge(data, lo, mid, hi); 153 } 154 //合併 155 private static void merge(Comparable[] data, int lo, int mid, int hi) { 156 //定義三個指標 157 int i = lo, p1 = lo, p2 = mid + 1; 158 //遍歷,移動p1指標和p2指標,比較對應索引處的值,找出小的那個,放到輔助陣列的對應索引處 159 while(p1 <= mid && p2 <= hi) { 160 if(!Sort.greater(data[p1], data[p2])) { 161 assist[i++] = data[p1++]; 162 } else { 163 assist[i++] = data[p2++]; 164 } 165 } 166 //遍歷,如果p1指標沒有走完,那麼順序移動p1指標,把對應的元素放到輔助陣列的對應索引處 167 while(p1 <= mid) { 168 assist[i++] = data[p1++]; 169 } 170 //遍歷,如果p2指標沒有走完,那麼順序移動p1指標,把對應的元素放到輔助陣列的對應索引處 171 while(p2 <= hi) { 172 assist[i++] = data[p2++]; 173 } 174 //把輔助陣列中的元素拷貝到原陣列中 175 for(int index = lo; index <= hi; index++) { 176 data[index] = assist[index]; 177 } 178 } 179 } 180 181 //快速排序 182 static class QuickSort implements Sort { 183 @Override 184 public String sortName() { 185 return "快速排序"; 186 } 187 @Override 188 public Comparable[] sort(Comparable[] data) { 189 int lo = 0, hi = data.length - 1; 190 sort(data, lo, hi); 191 return data; 192 } 193 //遞迴體 194 private static void sort(Comparable[] data, int lo, int hi) { 195 if(hi <= lo) return; 196 int partition = partition(data, lo, hi); 197 sort(data, lo, partition - 1); 198 sort(data, partition + 1, hi); 199 } 200 //分組 201 private static int partition(Comparable[] data, int lo, int hi) { 202 //確定分界值 203 Comparable key = data[lo]; 204 //定義兩個指標,分別指向待切分元素的最小索引處和最大索引處的下一個位置 205 int left = lo, right = hi + 1; 206 //切分 207 while(true) { 208 //先從左往右掃描,移動right指標,找到一個比分界值小的元素,停止 209 while(!Sort.greater(key, data[--right])) { 210 if(right == lo) break; 211 } 212 //再從左往右掃描,移動left指標,找到一個比分界值大的元素,停止 213 while(!Sort.greater(data[++left], key)) { 214 if(left == hi) break; 215 } 216 //判斷left>=right,如果是,則證明元素掃描完畢,結束迴圈,如果不是,則交換元素即可 217 if(left >= right) { 218 break; 219 } else { 220 Sort.swap(data, left, right); 221 } 222 } 223 //交換分界值 224 Sort.swap(data, lo, right); 225 return right; 226 } 227 } 228 229 //動態代理執行測試 230 static class DynamicSort { 231 //動態代理處理器 232 static class SortInvocationHandler implements InvocationHandler { 233 private Sort sort; 234 SortInvocationHandler(Sort sort) { this.sort = sort;} 235 @Override 236 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 237 System.out.printf("-------------測試%s演算法-------------\n", sort.sortName()); 238 Comparable[] data = (Comparable[])args[0]; 239 System.out.printf("排序前資料:%s\n", Arrays.toString(data)); 240 long start = System.currentTimeMillis(); 241 data = (Comparable[]) method.invoke(sort, args); 242 long end = System.currentTimeMillis(); 243 System.out.printf("排序後資料:%s\n", Arrays.toString(data)); 244 System.out.printf("排序總耗時:%s毫秒\n", end - start); 245 return null; 246 } 247 } 248 //執行代理 249 public static void sort(Comparable[] data, Class clazz) throws Throwable { 250 Sort sort = (Sort) clazz.getDeclaredConstructor().newInstance(); 251 sort = (Sort)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new SortInvocationHandler(sort)); 252 sort.sort(data); 253 } 254 } 255 256 //NIO載入資料 257 public static<T> T[] loadData(Class<T> c) throws Throwable{ 258 FileInputStream fileInputStream = new FileInputStream(Sort.class.getClassLoader().getResource("data.txt").getPath()); 259 FileChannel fileChannel = fileInputStream.getChannel(); 260 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); 261 StringBuffer stringBuffer = new StringBuffer(); 262 int length = -1; 263 while((length = fileChannel.read(byteBuffer)) != -1) { 264 byteBuffer.clear(); 265 byte[] bytes = Arrays.copyOf(byteBuffer.array(), length); 266 stringBuffer.append(new String(bytes)); 267 } 268 fileChannel.close(); 269 fileInputStream.close(); 270 return (T[]) Arrays.stream(stringBuffer.toString().split(",")).mapToInt(Integer::valueOf).boxed().toArray(Integer[]::new); 271 } 272 273 //啟動類 274 public static void main(String args[]) throws Throwable { 275 Comparable[] data = loadData(Integer.class); 276 //測試氣泡排序 277 DynamicSort.sort(Arrays.copyOf(data, data.length), BubbleSort.class); 278 //測試選擇排序 279 DynamicSort.sort(Arrays.copyOf(data, data.length), SelectionSort.class); 280 //測試插入排序 281 DynamicSort.sort(Arrays.copyOf(data, data.length), InsertionSort.class); 282 //測試希爾排序 283 DynamicSort.sort(Arrays.copyOf(data, data.length), ShellSort.class); 284 //測試歸併排序 285 DynamicSort.sort(Arrays.copyOf(data, data.length), MergeSort.class); 286 //測試快速排序 287 DynamicSort.sort(Arrays.copyOf(data, data.length), QuickSort.class); 288 } 289 290 }

執行結果