演算法不光是要會寫,更重要的是要理解記住它的思想
氣泡排序
外層迴圈是表示的內層迴圈需要對比的次數,內層迴圈每結束一次都會得出未排列出的部分的最大值 時間複雜度是O(n^2),空間複雜度是O(1),重要的是flag標誌是在內層迴圈結束後會做一次判斷,如果整個內層迴圈都未曾改變flag的值,說明陣列已經是有序的
/**
* 氣泡排序
*
* @param a
*/
private void bubbleSort(int[] a) {
//選出最大的元素需要length-1次比較
for (int i = a.length - 1; i > 0; i--) {
boolean flag = false;
for (int j = 0; j < i; j++) {
if (a[j] > a[j + 1]) {
int tmp = a[j + 1];
a[j + 1] = a[j];
a[j] = tmp;
flag = true;
}
}
//沒有交換說明已經成序
if (!flag)
break;
}
System.out.println("氣泡排序結果:" + Arrays.toString(a));
}
複製程式碼
選擇排序
/**
* 選擇排序
*
* @param a
*/
private void selectSort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
int min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[min] > a[j])
min = j;
}
if (min != i) {
int tmp = a[min];
a[min] = a[i];
a[i] = tmp;
}
}
System.out.println("選擇排序結果:" + Arrays.toString(a));
}
複製程式碼
插入排序
/**
* 插入排序
*
* @param a
*/
private void insertSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int j;
for (j = i - 1; j >= 0; j--) {
//找到第一個比a[i]小的索引
if (a[j] < a[i])
break;
}
if (j != i - 1) {
//每個元素向後移動一位
for (int k = i - 1; k > j; k--) {
a[k + 1] = a[k];
}
a[j + 1] = a[i];
}
}
System.out.println("插入排序結果:" + Arrays.toString(a));
}
複製程式碼
桶排序
/**
* 桶排序
*
* @param a
*/
private void bucketSort(int[] a) {
int max = 0;
for (int i : a) {
if (i > max)
max = i;
}
//初始化水桶max+1個
int[] buckets = new int[max + 1];
for (int i = 0; i < a.length; i++) {
buckets[a[i]]++;
}
int index = 0;
for (int i = 0; i < buckets.length; i++) {
int key = buckets[i];
while (key-- > 0) {
a[index++] = i;
}
}
System.out.println("桶排序結果:" + Arrays.toString(a));
}
複製程式碼
快速排序
/*************************快速排序*****************************/
private void quickSort(int[] a) {
quickSort(a, 0, a.length - 1);
System.out.println("快速排序結果:" + Arrays.toString(a));
}
private void quickSort(int[] a, int left, int right) {
if (left < right) {
int head = left;
int tail = right;
int x = a[head];
while (head < tail) {
while (head < tail && a[tail] > x)
tail--;
if (head < tail)
a[head++] = a[tail];
while (head < tail && a[head] > x)
head++;
if (head < tail)
a[tail--] = a[head];
}
a[head] = x;
quickSort(a, left, head - 1);
quickSort(a, head + 1, right);
}
}
複製程式碼
堆排序
/****************************堆排序*****************************/
private void heapSort(int[] a) {
for (int i = a.length / 2 - 1; i >= 0; i--) {
maxHeapSort(a, i, a.length - 1);
}
for (int i = a.length - 1; i > 0; i--) {
//a[0]為最大元素,至於末尾
int tmp = a[0];
a[0] = a[i];
a[i] = tmp;
maxHeapSort(a, 0, i - 1);
}
System.out.println("堆排序結果:" + Arrays.toString(a));
}
/**
* 利用最大堆找出最大的元素
*
* @param a
* @param start
* @param end
*/
private void maxHeapSort(int[] a, int start, int end) {
int c = start;
//左孩子
int left;
int tmp = a[c];
for (left = 2 * c + 1; left <= end; c = left, left = 2 * left + 1) {
//選擇左右孩子中較大的一個
if (left < end && a[left] < a[left + 1])
left++;
if (tmp >= a[left])
break;
else {
a[c] = a[left];
a[left] = tmp;
}
}
}
複製程式碼
希爾排序
/**
* 希爾排序,用步長再插入
*
* @param a
*/
private void shellSort(int[] a) {
int n = a.length;
//步長每次除以2
for (int gap = n / 2; gap > 0; gap = gap / 2) {
//對每組進行插入排序
for (int i = 0; i < gap; i++) {
shellSort(a, i, gap);
}
}
System.out.println("希爾排序結果:" + Arrays.toString(a));
}
private void shellSort(int[] a, int start, int gap) {
//這裡純粹是一個插入排序
for (int j = start + gap; j < a.length; j = j + gap) {
int k;
for (k = j - gap; k >= start; k = k - gap) {
if (a[k] < a[j])
break;
}
if (k != j - gap) {
for (int i = j - gap; i > k; i = i - gap) {
a[i + 1] = a[i];
}
a[k + gap] = a[j];
}
}
}
複製程式碼
基數排序
/***************************基數排序**************************/
private void radixSort(int[] a) {
int max = 0;
for (int i : a) {
if (max < i)
max = i;
}
for (int exp = 1; max / exp > 0; exp *= 10) {
radixSort(a, exp);
}
System.out.println("基數排序結果:" + Arrays.toString(a));
}
private void radixSort(int[] a, int exp) {
int[] output = new int[a.length];
int[] buckets = new int[10];
for (int i = 0; i < a.length; i++) {
buckets[(a[i] / exp) % 10]++;
}
for (int i = 1; i < 10; i++) {
buckets[i] += buckets[i - 1];
}
for (int i = a.length - 1; i >= 0; i--) {
int index = (a[i] / exp) % 10;
output[buckets[index] - 1] = a[i];
buckets[index]--;
}
for (int i = 0; i < output.length; i++) {
a[i] = output[i];
}
}
複製程式碼
歸併排序
/**************************歸併排序***************************/
private void mergeSort(int[] a) {
mergeSort(a, 0, a.length - 1);
System.out.println("歸併排序結果:" + Arrays.toString(a));
}
private void mergeSort(int[] a, int start, int end) {
if (start < end) {
int mid = (end + start) / 2;
mergeSort(a, start, mid);
mergeSort(a, mid + 1, end);
merge(a, start, mid, end);
}
}
private void merge(int[] a, int start, int mid, int end) {
int[] output = new int[end - start + 1];
int index = 0;
int i = start;
int j = mid + 1;
while (i <= mid && j <= end) {
if (a[i] < a[j])
output[index++] = a[i++];
if (a[j] < a[i])
output[index++] = a[j++];
while (i <= mid) {
output[index++] = a[i++];
}
while (j <= end) {
output[index++] = a[j++];
}
}
for (int k = 0; k < output.length; k++) {
a[start + k] = output[k];
}
}
複製程式碼
計數排序
/**
* 計數排序
*
* @param a
*/
private void countSort(int[] a) {
//找出最大值和最小值
int min = a[0], max = a[0];
for (int i : a) {
if (min > i)
min = i;
if (max < i)
max = i;
}
//初始化桶
int[] buckets = new int[max - min + 1];
for (int i = 0; i < a.length; i++) {
buckets[a[i] - min]++;
}
//這裡和基數排序一樣
for (int i = 1; i < max - min + 1; i++) {
buckets[i] += buckets[i - 1];
}
int[] output = new int[a.length];
for (int i = a.length - 1; i >= 0; i--) {
output[buckets[a[i] - min] - 1] = a[i];
buckets[a[i] - min]--;
}
for (int i = 0; i < output.length; i++) {
a[i] = output[i];
}
System.out.println("計數排序結果:" + Arrays.toString(a));
}
複製程式碼
測試用例
private static final int[] SORT_ARRAY = {43, 64, 21, 6565, 3424, 22, 6523, 345, 89, 68, 162, 528};
public static void main(String[] args) {
Sort sort = new Sort();
sort.bubbleSort(SORT_ARRAY);
sort.selectSort(SORT_ARRAY);
sort.insertSort(SORT_ARRAY);
sort.bucketSort(SORT_ARRAY);
sort.quickSort(SORT_ARRAY);
sort.heapSort(SORT_ARRAY);
sort.shellSort(SORT_ARRAY);
sort.radixSort(SORT_ARRAY);
sort.mergeSort(SORT_ARRAY);
sort.countSort(SORT_ARRAY);
}
複製程式碼
測試結果
氣泡排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
選擇排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
插入排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
桶排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
快速排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
堆排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
希爾排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
基數排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
歸併排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
計數排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
複製程式碼