20200104:重溫十大排序

溫故而知新,可以爲師矣

重新過一下已經掌握的排序方法,最基礎的東西往往最關鍵!

寫在最前面

新年伊始就得了場感冒,咳嗽從19年咳到了20年,考完研也休息的差不多了,大家一起共勉!

文章框架

在這裏插入圖片描述

快速排序

package com.immunize.December.sort;
 
/**
 * 快速排序1.2
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Quick3 {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序後的數組");
   quickSort(a, 0, a.length - 1);
   // SimpleSelectSort2(a);
   Print(a);
 }
 
 
 public static void quickSort(int[] a, int left, int right) {
   int q;
   if (left < right) {
    q = Partition(a, left, right);
    quickSort(a, left, q - 1);
    quickSort(a, q + 1, right);
   }
 
 }
 
 private static int Partition(int[] a, int left, int right) {
   int i, j, s;
   s = a[right];
   i = left - 1;
   for (j = left; j < right; j++) {
    if (a[j] <= a[right]) {
      i++;
      Swap(a, i, j);
    }
   }
   Swap(a, i + 1, right);
   return i + 1;
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

上面這個版本是最優的改進版本,因爲快速排序的精髓在與找到最優的標準,以下附上以數組中間值作爲標準來進行比較的快排代碼:

package com.immunize.December.sort;

/**
 * 快速排序1.1
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Quick2 {

	public static void main(String[] args) {
		// 生成一個隨機的數組
		int[] a = Generate(100, 10);
		// 對這個數組進行打印
		System.out.println("原始數組:");
		Print(a);
		// Print(Arrays.copyOfRange(a, 0, a.length));
		System.out.println("排序後的數組");
		QuickSort(a, 0, a.length - 1);
		// SimpleSelectSort2(a);
		Print(a);
	}

	/*
	 * 6 2 5 4 8 9 4 2 5 6 8 9 2 4 5 6 8 9
	 * 
	 */
	public static void QuickSort(int[] a, int left, int right) {
		int i, j, crit;
		if (left > right)
			return;
		i = left - 1;
		j = right + 1;
		// crit = a[0];
		crit = a[(left + right) / 2];
		while (true) {
			while (a[++i] < crit)
				;
			while (a[--j] > crit)
				;
			if (i >= j)
				break;
			Swap(a, i, j);
		}
		QuickSort(a, left, i - 1);
		QuickSort(a, j + 1, right);
	}

	// Print函數
	public static void Print(int[] arr) {
		System.out.print("[");
		for (int i = 0; i < arr.length; i++) {
			if (i == arr.length - 1) {
				System.out.print(arr[i]);
				break;
			}
			System.out.print(arr[i] + ",");
		}
		System.out.print("]");
		System.out.println();
	}

	// 隨機生成n個數字,組成隨機數組函數Generate函數
	public static int[] Generate(int max, int length) {
		int[] arr = new int[length];
		for (int i = 0; i < length; i++) {
			arr[i] = (int) (Math.random() * max);
		}
		return arr;
	}

	// Swap函數
	public static void Swap(int[] arr, int i, int j) {
		int tmp = 0;
		tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
}

快速排序的最差時間複雜度爲O(n²),但在大多數時候的效率是很好的,必須掌握。以下排序僅附上代碼重寫,不再贅述原理

堆排序

package com.immunize.December.sort;
 
/**
 * Heap排序:基於選擇排序的改進
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Heap {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序後的數組");
   HeapSort(a);
   // SimpleSelectSort2(a);
   Print(a);
 }
 
 // 堆排序
 public static void HeapSort(int[] arr) {
   // 構造大根堆
   HeapInsert(arr);
   int size = arr.length;
   while (size > 1) {
    // 交換大根和最後一個值,即固定最大值
    Swap(arr, 0, size - 1);
    // size遞減
    size--;
 
    Heapify(arr, 0, size);
   }
 
 }
 
 // 構造大根堆(通過新插入的數上升)
 public static void HeapInsert(int[] arr) {
   // 定義所使用的變量
   int i, curIndex, faIndex;
   for (i = 0; i < arr.length; i++) {
    // 確定當前索引值
    curIndex = i;
    // 計算父節點索引值
    faIndex = (curIndex - 1) / 2;
    // 遍歷,構造大根堆
    while (arr[curIndex] > arr[faIndex]) {
      Swap(arr, curIndex, faIndex);
      // 將當前索引和父節點索引歸位
      curIndex = faIndex;
      faIndex = (curIndex - 1) / 2;
    }
   }
 }
 
 // 將剩餘的數構造成大根堆(通過頂端的數下降)
 public static void Heapify(int[] arr, int index, int size) {
   // 定義使用的變量
   int left, right, largerIndex;
   // 計算當前節點的左右節點索引
   left = 2 * index + 1;
   right = 2 * index + 2;
   // 確保較小的子節點:左節點小於待排序節點個數
   while (left < size) {
    // 找到左右節點中較大的節點索引
    if (arr[left] < arr[right] && right < size)
      largerIndex = right;
    else
      largerIndex = left;
 
    // 比較當前索引和左右節點中較大的索引處的值,若當前索引較大,則已經是大根堆,跳出循環即可。
    if (arr[index] > arr[largerIndex]) {
      largerIndex = index;
      break;
    }
    Swap(arr, index, largerIndex);
    // 重新指向當前索引和當前索引的左右子節點
    index = largerIndex;
    left = 2 * index + 1;
    right = 2 * index + 2;
 
   }
 }
 
 // 交換數組中兩個元素的值
 public static void Swap(int[] arr, int i, int j) {
   int temp = arr[i];
   arr[i] = arr[j];
   arr[j] = temp;
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
}
 

希爾排序

package com.immunize.December.sort;
 
public class Shell {
 public static void main(String[] args) {
 
   // 生成原始數組
   int[] a = Generate(100, 10);
   // 原始數組打印
   System.out.println("原始數組:");
   Print(a);
   // 希爾排序後的數組打印
   System.out.println("排序後的數組");
   // shellSort1(a);
   shellSort2(a);
   Print(a);
 }
 
 public static void shellSort2(int[] a) {
   int gap = a.length / 2;
   int i, j;
   for (; gap > 0; gap /= 2) {
    for (i = gap; i < a.length; i++) {
      j = i;
      while (j - gap >= 0 && a[j] < a[j - gap]) {
       Swap(a, j, j - gap);
       j -= gap;
      }
    }
   }
 }
 
 // 希爾排序
 public static void shellSort1(int[] arr) {
   int i, j, k, tmp;
   int gap = arr.length / 2;
   while (gap > 0) {
    for (k = 0; k < gap; k++) {
      for (i = k + gap; i < arr.length; i += gap) {
       for (j = i - gap; j >= k; j -= gap) {
         if (arr[j] > arr[j + gap]) {
          Swap(arr, j, j + gap);
         } else {
          break;
         }
       }
      }
    }
    gap /= 2;
   }
 
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

計數排序

 
package com.immunize.December.sort;
 
public class Count {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序後的數組");
   Print(countSort(a));
 
 }
 
 public static int[] countSort(int[] a) {
   // 找出數組中的最大值
   int max = Integer.MIN_VALUE;
   for (int num : a) {
    max = Math.max(max, num);
   }
 
   // 初始化計數數組
   int[] count = new int[max + 1];
   // 對數組計數
   for (int num : a) {
    count[num]++;
   }
 
   // 創建結果數組
   int[] result = new int[a.length];
   int index = 0;
   for (int i = 0; i < count.length; i++) {
    while (count[i] > 0) {
      result[index++] = i;
      count[i]--;
    }
   }
   return result;
 
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

桶排序

package com.immunize.December.sort;
 
public class Radix {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   System.out.println("排序後的數組");
   RadixSort(a, 3);
   Print(a);
 }
 
 public static void RadixSort(int[] arr, int max) {
 
   // count數組用來計數
   int[] count = new int[arr.length];
   // bucket用來當桶(在下面你就理解了什麼是桶了),放數據,取數據
   int[] bucket = new int[arr.length];
 
   // k表示第幾位,1代表個位,2代表十位,3代表百位
   for (int k = 1; k <= max; k++) {
    // 把count置空,防止上次循環的數據影響
    for (int i = 0; i < arr.length; i++) {
      count[i] = 0;
    }
 
    // 分別統計第k位是0,1,2,3,4,5,6,7,8,9的數量
    // 以下便稱爲桶
    // 即此循環用來統計每個桶中的數據的數量
    for (int i = 0; i < arr.length; i++) {
      count[getFigure(arr[i], k)]++;
    }
 
    // 利用count[i]來確定放置數據的位置
    for (int i = 1; i < arr.length; i++) {
      count[i] = count[i] + count[i - 1];
    }
    // 執行完此循環之後的count[i]就是第i個桶右邊界的位置
 
    // 利用循環把數據裝入各個桶中,注意是從後往前裝
    // 這裏是重點,一定要仔細理解
    for (int i = arr.length - 1; i >= 0; i--) {
      int j = getFigure(arr[i], k);
      bucket[count[j] - 1] = arr[i];
      count[j]--;
    }
 
    // 將桶中的數據取出來,賦值給arr
    for (int i = 0, j = 0; i < arr.length; i++, j++) {
      arr[i] = bucket[j];
    }
 
   }
 }
 
 // 此函數返回整型數i的第k位是什麼
 public static int getFigure(int i, int k) {
   int[] a = { 1, 10, 100 };
   return (i / a[k - 1]) % 10;
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

冒泡排序

package com.immunize.December.sort;
 
public class Bubble {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序後的數組");
   bubbleSort(a);
   // SimpleSelectSort2(a);
   Print(a);
 
 }
 
 public static void bubbleSort(int[] a) {
   // 兩兩對比,每次將最大的放到最後面
   int i, j;
   // i爲遍歷指針,從0-a.length-2
   for (i = 0; i < a.length - 1; i++) {
    // j爲比較指針,從1-(a.length-i)
    for (j = 1; j < a.length - i; j++) {
      if (a[j] < a[j - 1])
       Swap(a, j, j - 1);
    }
   }
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

雞尾酒排序

package com.immunize.December.sort;
 
import java.util.Arrays;
 
public class Shaker {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序後的數組");
   ShakerSort(a);
   // SimpleSelectSort2(a);
   Print(a);
   // Print(cocktailSort(a));
 }
 
 public static void ShakerSort(int[] a) {
   int i, j, left, right, shift;
   left = 0;
   right = a.length - 1;
   shift = 0;
   while (left < right) {
 
    for (i = left; i < right; i++) {
      if (a[i] > a[i + 1]) {
       Swap(a, i, i + 1);
       shift = i;
      }
    }
    right = shift;
    for (j = right; j > left; j--) {
      if (a[j - 1] > a[j]) {
       Swap(a, j, j - 1);
       shift = j;
      }
    }
    left = shift;
   }
 }
 
 public static int[] cocktailSort(int[] src) {
   int len = src.length;
   // 將最小值排到隊尾
   for (int i = 0; i < len / 2; i++) {
    for (int j = i; j < len - i - 1; j++) {
      if (src[j] < src[j + 1]) {
       int temp = src[j];
       src[j] = src[j + 1];
       src[j + 1] = temp;
      }
      System.out.println("交換小" + Arrays.toString(src));
    }
    // 將最大值排到隊頭
    for (int j = len - 1 - (i + 1); j > i; j--) {
      if (src[j] > src[j - 1]) {
       int temp = src[j];
       src[j] = src[j - 1];
       src[j - 1] = temp;
      }
      System.out.println("交換大" + Arrays.toString(src));
    }
    System.out.println("第" + i + "次排序結果:" + Arrays.toString(src));
   }
   return src;
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

雞尾酒排序這裏多說一點,兩種寫法都在代碼中呈現出來,ShakerSort/cocktailSort都稱爲雞尾酒排序

選擇排序

package com.immunize.December.sort;
 
import java.util.Arrays;
 
public class Select {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序後的數組");
   // selectSort1(a);
   selectSort2(a);
 
   // SimpleSelectSort2(a);
   Print(a);
 }
 
 public static void selectSort1(int[] a) {
   int i, j, tmp;
   for (i = 0; i < a.length - 1; i++) {
    // 獲取當前索引
    tmp = i;
    for (j = i + 1; j < a.length; j++) {
      if (a[tmp] > a[j]) {
       Swap(a, j, tmp);
      }
    }
   }
 }
 
 public static void selectSort2(int[] a) {
   int i, j, tmp;
   for (i = 0; i < a.length - 1; i++) {
    tmp = i;
    Swap(a, tmp, FindMinIndex(Arrays.copyOfRange(a, i, a.length)) + i);
   }
 }
 
 public static int FindMinIndex(int[] a) {
   int i, min, minIndex = 0;
   min = a[0];
   for (i = 1; i < a.length; i++) {
    if (a[i] < min) {
      min = a[i];
      minIndex = i;
    }
   }
   return minIndex;
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

插入排序

package com.immunize.December.sort;
 
public class Insert {
 
 public static void main(String[] args) {
   // 生成一個隨機的數組
   int[] a = Generate(100, 10);
   // 對這個數組進行打印
   System.out.println("原始數組:");
   Print(a);
   System.out.println("排序後的數組");
   insertSort(a);
   // SimpleSelectSort2(a);
   Print(a);
 
 }
 
 // 插入排序
 public static void insertSort(int[] a) {
   int i, j, tmp;
   // 遍歷
   // i從1-末尾
   for (i = 1; i < a.length; i++) {
    // 當前值tmp
    tmp = a[i];
    // 前一個值的索引
    j = i - 1;
    // 當前值與每一個在其之前的數比較
    while (tmp < a[j]) {
      // 前值較大的話則需要往後移
      a[j + 1] = a[j];
      j--;
      // 移動的上限是第一個值
      if (j == -1) {
       break;
      }
    }
    // 跳出循環,當前值賦值到空出來的那個位置
    a[j + 1] = tmp;
   }
 }
 
 // Print函數
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 隨機生成n個數字,組成隨機數組函數Generate函數
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函數
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

基數排序

package com.immunize.Arithmetic;
 
/**
 * 基數排序法
 * 
 * @author Mr IMMUNIZE
 *
 */
public class RadixSort {
 
  public static void main(String[] args) {
     int[] data = { 73, 22, 93, 43, 55, 14, 28, 65, 39, 81 };
     int[][] temp = new int[10][10];
     int[] order = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     int i, j, k, n, lsd;
     k = 0;
     n = 1;
     System.out.println("排序前:");
     Print(data);
     System.out.println();
     while (n <= 10) {
       for (i = 0; i < 10; i++) {
          // 拿到個位數數字
          lsd = ((data[i] / n) % 10);
          // 將該數據存放在對應的列上,21就放在第一列,89就放在第9列
          temp[lsd][order[lsd]] = data[i];
          // order[lsd]表示行數,行數遞增
          order[lsd]++;
       }
 
       for (i = 0; i < 10; i++) {
          // 重新排列,先列後行
          if (order[i] != 0) {
            // 先列再行,每一行只有一個數據,每一列的數據按照行序排列
            for (j = 0; j < order[i]; j++) {
               data[k] = temp[i][j];
               k++;
            }
          }
          order[i] = 0;
       }
       n *= 10;
       k = 0;
     }
     System.out.println("排序後:");
     Print(data);
  }
 
  public static void Print(int[] number) {
 
     for (int i = 0; i < number.length; i++) {
       System.out.print(number[i] + " ");
     }
  }
}
 
 

基數排序代碼未重寫,是直接取自我之前20191015的博客。

結語

至此,十大排序除了歸併排序其餘的都已經附上重寫代碼,而歸併排序實際上是Java中Arrays的sort方法的本質,我們明天給予說明。

發佈了99 篇原創文章 · 獲贊 11 · 訪問量 4188
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章