項目地址:https://github.com/windwant/windwant-service/tree/master/algorithm
冒泡排序:兩兩比較,大數冒泡
升序:
public static void bubbleSort(int[] arr){ int lgn = arr.length; for (int i = 0; i < lgn - 1; i++) { for (int j = 0; j < lgn - 1 - i; j++) { if(arr[j] > arr[j + 1]){ int temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } }
降序:
...
選擇排序:選擇剩余元素中最小(最大)的元素放置到初始選擇集合中(空)
public static void SelectionSortAsc(int[] arr){
int min = 0;
for (int i = 0; i < arr.length - 1; i++) {
min = i;
for (int j = i + 1; j < arr.length ; j++) {
if(arr[j] < arr[min]){
min = j;
}
}
if(min != i){
int tmp = arr[i];
arr[i] = arr[min];
arr[min] = tmp;
}
}
}
public static void SelectionSortDesc(int[] arr){
int max = 0;
for (int i = 0; i < arr.length - 1; i++) {
max = i;
for (int j = i + 1; j < arr.length ; j++) {
if(arr[j] > arr[max]){
max = j;
}
}
if(max != i){
int tmp = arr[i];
arr[i] = arr[max];
arr[max] = tmp;
}
}
}
插入排序:設定一個初始已排序的集合(一般選擇一個元素),從剩余的集合中將各個元素以此插入到初始集合中的正確位置
public static void insertionSort(int [] array){ for(int i = 1; i < array.length; i++){ int temp = array[i];//被標記的值或者說是當前需要插入的值 int j = i; //如果輪循值大於被標記值則往后移 while( j > 0 && temp < array[j - 1]){ array[j] = array[j - 1]; j-- ; } //將被標記值插入最終移出的空位置 array[j] = temp; } }
快速排序:選取錨點,划分小於,大於兩個集合,遞歸處理子集合
public static void quikeSort(int[] arr, int low, int high) { int start = low; int end = high; int anchor = arr[low]; while (end > start) { //比較 anchor---end while (end > start && arr[end] >= anchor) { //從末尾向前尋找小於等於anchor的值 end--; } //交換位置 if (arr[end] <= anchor) { int temp = arr[end]; arr[end] = arr[start]; arr[start] = temp; } //比較start---anchor while (end > start && arr[start] <= anchor) {//從起始位置向后尋找大於等於anchor的值 start++; } //交換位置 if (arr[start] >= anchor) { int temp = arr[start]; arr[start] = arr[end]; arr[end] = temp; } } //anchor位置確定。左邊的元素值都小於anchor值,右邊的值都大於anchor值,遞歸排序左右兩側排序 //左邊元素。low---anchor值索引-1 if (start > low) { quikeSort(arr, low, start - 1); } //右邊元素。從anchor值索引+1---high if (end < high) { quikeSort(arr, end + 1, high); } }
歸並排序:中分兩個結合,分別歸並排序,然后合並兩個有序結合;遞歸進行
public static void mergeSort(int[] data) { sort(data, 0, data.length - 1); } public static void sort(int[] data, int left, int right) { if (left >= right) return; // 找出中間索引 int center = (left + right) / 2; // 對左邊數組進行遞歸 sort(data, left, center); // 對右邊數組進行遞歸 sort(data, center + 1, right); // 合並 merge(data, left, center, right); } /** * 將兩個數組進行歸並,歸並前面2個數組已有序,歸並后依然有序 * * @param data * 數組對象 * @param left * 左數組的第一個元素的索引 * @param center * 左數組的最后一個元素的索引,center+1是右數組第一個元素的索引 * @param right * 右數組最后一個元素的索引 */ public static void merge(int[] data, int left, int center, int right) { // 臨時數組 int[] tmpArr = new int[data.length]; // 右數組第一個元素索引 int mid = center + 1; // third 記錄臨時數組的索引 int third = left; // 緩存左數組第一個元素的索引 int tmp = left; while (left <= center && mid <= right) { // 從兩個數組中取出最小的放入臨時數組 if (data[left] <= data[mid]) { tmpArr[third++] = data[left++]; } else { tmpArr[third++] = data[mid++]; } } // 剩余部分依次放入臨時數組(實際上兩個while只會執行其中一個) while (mid <= right) { tmpArr[third++] = data[mid++]; } while (left <= center) { tmpArr[third++] = data[left++]; } // 將臨時數組中的內容拷貝回原數組中 // (原left-right范圍的內容被復制回原數組) while (tmp <= right) { data[tmp] = tmpArr[tmp++]; } }
基數排序:逐位排序
//LSD public static void radixLSDSort(int[] arr){ //最高位數 int maxBit = getMaxBit(arr); //十個bulk 分別存放 每個位數 數字 相應的元素 如個位為3 則放入bulk[3] Queue<Integer>[] bulk = new Queue[10]; for (int i = 0; i < bulk.length; i++) { bulk[i] = new ArrayDeque(); } //分別處理不同位數 存放 處理 for (int i = 0; i < maxBit; i++) { for (int j = 0; j < arr.length; j++) { int ivalue = (int) (arr[j] % Math.pow(10, i + 1) / Math.pow(10, i)); //去相應位數上的數字作為 存入bulk index bulk[ivalue].offer(arr[j]); } //取出bulk中的元素 重新放入數組 並清除bulk中的元素。 int arrIndex = 0; for (int j = 0; j < bulk.length; j++) { while (bulk[j].size()>0){ arr[arrIndex++] = bulk[j].poll(); } } } } public static int getMaxBit(int[] arr){ int max = arr[0]; for (int i = 1; i < arr.length; i++) { if(arr[i] > max){ max = arr[i]; } } int b = 0; while (max > 0){ max /= 10; b++; } return b; } public static void radixMSDSort(int[] arr){ msdSort(arr, 0, arr.length, getMaxBit(arr)); } //MSD public static void msdSort(int[] arr, int left, int right, int maxBit){ //十個bulk 分別存放 每個位數 數字 相應的元素 如個位為3 則放入bulk[3] Queue<Integer>[] bulk = new Queue[10]; for (int i = 0; i < bulk.length; i++) { bulk[i] = new ArrayDeque(); } //依據最高位分別放入不同的bulk for (int j = left; j < right; j++) { int ivalue = (int) (arr[j] % Math.pow(10, maxBit) / Math.pow(10, maxBit - 1)); //去相應位數上的數字作為 存入bulk index bulk[ivalue].offer(arr[j]); } //取出bulk中的元素 重新放入數組 並清除bulk中的元素。記錄bulk中queue大小大於1的數組索引 遞歸使用 List<Integer> count = new ArrayList<Integer>(); int arrIndex = left; for (int j = 0; j < bulk.length; j++) { int start = arrIndex; while (bulk[j].size()>0){ arr[arrIndex++] = bulk[j].poll(); } if(arrIndex - start > 1){ count.add(start); count.add(arrIndex); } } //遞歸最小位判斷 int nextBit = maxBit - 1; if(nextBit > 0) { for (int i = 1; i < count.size(); i += 2) { msdSort(arr, count.get(i - 1), count.get(i), nextBit); } } }
shell排序:插入排序+步長改進
public static void shellSort(int[] arr){ int step = arr.length/2; while (step >= 1) { //步長為1時 包含所有數組序列 for (int i = 0; i < step; i++) { //步長為n則數組將分為n組分別排序 for (int j = step + i; j < arr.length; j += step) { //對跨步長每組元素進行插入排序 int temp = arr[j]; int preIndex = j - step; while (preIndex > -1 && temp < arr[preIndex]) { arr[preIndex + step] = arr[preIndex]; preIndex -= step; } arr[preIndex + step] = temp; System.out.println(" middle: " + Arrays.toString(arr)); } } step /= 2; //每次步長處理 } }
/**
* 改進形式
* @param arr
*/
public static void shellSort1(int[] arr){
int step = arr.length/2;
while (step >= 1) { //步長為1時 包含所有數組序列
for (int i = step; i < arr.length; i += step) { //對跨步長每組元素進行插入排序
int temp = arr[i];
int j = i;
while (j > 0 && temp < arr[j - step]) {
arr[j] = arr[j - step];
j -= step;
}
arr[j] = temp;
}
System.out.println("step: " + step + " middle: " + Arrays.toString(arr));
step /= 2; //每次步長處理
}
}
