JAVA经典百题之排序算法

题目:排序算法

1. 冒泡排序 (Bubble Sort)

解题思路:
  • 依次比较相邻的元素,将较大的元素交换至右侧。
  • 重复这个过程,直到整个数组有序。
实现代码:
public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // Swap arr[j] and arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}
优缺点:
  • 优点:
    • 实现简单,代码短小。
  • 缺点:
    • 效率较低,时间复杂度为O(n^2)。

2. 选择排序 (Selection Sort)

解题思路:
  • 从数组中选择最小元素,与第一个元素交换位置。
  • 从剩余未排序的部分中选择最小元素,与第二个元素交换位置,依此类推。
实现代码:
public class SelectionSort {
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIdx = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIdx])
                    minIdx = j;
            }
            int temp = arr[minIdx];
            arr[minIdx] = arr[i];
            arr[i] = temp;
        }
    }
}
优缺点:
  • 优点:
    • 实现简单,不占用额外空间。
  • 缺点:
    • 效率较低,时间复杂度为O(n^2)。

3. 插入排序 (Insertion Sort)

解题思路:
  • 将数组分为已排序和未排序两部分,逐步将未排序的元素插入到已排序的部分。
实现代码:
public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) {
            int key = arr[i];
            int j = i - 1;
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            arr[j + 1] = key;
        }
    }
}
优缺点:
  • 优点:
    • 实现简单,对小规模数据或接近有序的数据排序效率高。
  • 缺点:
    • 效率较低,时间复杂度为O(n^2)。

4. 归并排序 (Merge Sort)

解题思路:
  • 将数组递归分成子数组,然后合并这些子数组,合并过程中保持有序。
实现代码:
public class MergeSort {
    public static void merge(int[] arr, int left, int middle, int right) {
        int n1 = middle - left + 1;
        int n2 = right - middle;

        int[] L = new int[n1];
        int[] R = new int[n2];

        for (int i = 0; i < n1; i++)
            L[i] = arr[left + i];
        for (int j = 0; j < n2; j++)
            R[j] = arr[middle + 1 + j];

        int i = 0, j = 0, k = left;

        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    public static void mergeSort(int[] arr, int left, int right) {
        if (left < right) {
            int middle = left + (right - left) / 2;

            mergeSort(arr, left, middle);
            mergeSort(arr, middle + 1, right);

            merge(arr, left, middle, right);
        }
    }
}
优缺点:
  • 优点:
    • 稳定,时间复杂度为O(n log n)。
  • 缺点:
    • 需要额外的内存空间。

5. 快速排序 (Quick Sort)

解题思路:
  • 选择一个基准元素,将数组分为小于基准和大于基准的两部分,然后递归地对这两部分进行排序。
实现代码:
public class QuickSort {
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = low - 1;

        for (int j = low; j < high; j++) {
            if (arr[j] < pivot) {
                i++;
                swap(arr, i, j);
            }
        }
        swap(arr, i + 1, high);
        return i + 1;
    }

    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pi = partition(arr, low, high);

            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);


        }
    }
}
优缺点:
  • 优点:
    • 效率高,时间复杂度平均情况下为O(n log n)。
  • 缺点:
    • 不稳定。

6. 堆排序 (Heap Sort)

解题思路:
  • 构建最大堆(或最小堆),将堆顶元素与最后一个元素交换,然后将堆的大小减一并重新维护堆的性质。
实现代码:
public class HeapSort {
    public static void heapify(int[] arr, int n, int i) {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;

        if (left < n && arr[left] > arr[largest])
            largest = left;

        if (right < n && arr[right] > arr[largest])
            largest = right;

        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;

            heapify(arr, n, largest);
        }
    }

    public static void heapSort(int[] arr) {
        int n = arr.length;

        for (int i = n / 2 - 1; i >= 0; i--)
            heapify(arr, n, i);

        for (int i = n - 1; i >= 0; i--) {
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            heapify(arr, i, 0);
        }
    }
}
优缺点:
  • 优点:
    • 高效的原地排序算法,时间复杂度为O(n log n)。
  • 缺点:
    • 不稳定。

7. 计数排序 (Counting Sort)

解题思路:
  • 统计数组中每个元素的出现次数,然后根据元素值和出现次数重新构建数组。
实现代码:
public class CountingSort {
    public static void countingSort(int[] arr) {
        int n = arr.length;

        int max = arr[0];
        for (int i = 1; i < n; i++) {
            if (arr[i] > max)
                max = arr[i];
        }

        int[] count = new int[max + 1];
        for (int i = 0; i <= max; i++)
            count[i] = 0;

        for (int i = 0; i < n; i++)
            count[arr[i]]++;

        for (int i = 1; i <= max; i++)
            count[i] += count[i - 1];

        int[] output = new int[n];
        for (int i = n - 1; i >= 0; i--) {
            output[count[arr[i]] - 1] = arr[i];
            count[arr[i]]--;
        }

        for (int i = 0; i < n; i++)
            arr[i] = output[i];
    }
}
优缺点:
  • 优点:
    • 适用于元素范围不大的情况,时间复杂度为O(n + k),k为最大元素值。
  • 缺点:
    • 对于元素范围很大的数据效率较低。

8. 桶排序 (Bucket Sort)

解题思路:
  • 将元素分配到不同的桶中,对每个桶中的元素进行排序,然后合并所有桶。
实现代码:
import java.util.ArrayList;
import java.util.Collections;

public class BucketSort {
    public static void bucketSort(int[] arr) {
        int n = arr.length;
        int max = arr[0];
        int min = arr[0];

        for (int i = 1; i < n; i++) {
            if (arr[i] > max)
                max = arr[i];
            if (arr[i] < min)
                min = arr[i];
        }

        int bucketCount = max - min + 1;
        ArrayList<ArrayList<Integer>> buckets = new ArrayList<>(bucketCount);

        for (int i = 0; i < bucketCount; i++)
            buckets.add(new ArrayList<>());

        for (int i = 0; i < n; i++) {
            int bucketIndex = (arr[i] - min) * (bucketCount - 1) / (max - min);
            buckets.get(bucketIndex).add(arr[i]);
        }

        int index = 0;
        for (int i = 0; i < bucketCount; i++) {
            Collections.sort(buckets.get(i));
            for (int j = 0; j < buckets.get(i).size(); j++)
                arr[index++] = buckets.get(i).get(j);
        }
    }
}
优缺点:
  • 优点:
    • 适用于元素分布均匀的情况,时间复杂度为O(n + k),k为桶的个数。
  • 缺点:
    • 占用较多内存。

总结和推荐

  • 推荐的排序算法: 归并排序和快速排序
  • 归并排序和快速排序都是高效的排序算法,时间复杂度为O(n log n),适用于各种规模的数据集。
  • 归并排序是稳定的,但需要额外的内存空间,适用于所有数据类型。
  • 快速排序是不稳定的,但在实践中通常比归并排序更快,适用于大规模数据集。

这里推荐归并排序作为首选,因为它是稳定的且不会对原始数据造成修改。如果在内存受限的情况下考虑,可以选择快速排序。Bubble Sort、Selection Sort 和 Insertion Sort 适用于小规模数据集或教学目的,不推荐用于实际应用。

你可能感兴趣的:(JAVA经典百题,排序算法,java,算法)