【Java】常见的排序算法

冒泡排序

private static void bubble(int[] a) {
	int j = a.length - 1;
	do {
		int x = 0;
		for (int i = 0; i < j; i++) {
			if (a[i] > a[i + 1]) {
				int t = a[i];
				a[i] = a[i + 1];
				a[i + 1] = t;
				x = i;
			}
		}
		j = x;
	} while (j != 0);
}

选择排序

public static void sort(int[] a) {
	// 1. 选择轮数 a.length - 1
	// 2. 交换的索引位置(right) 初始 a.length - 1, 每次递减
	for (int right = a.length - 1; right > 0 ; right--) {
		int max = right;
		for (int i = 0; i < right; i++) {
			if (a[i] > a[max]) {
				max = i;
			}
		}
		if(max != right) {
			int t = a[max];
			a[max] = a[right];
			a[right] = t;
		}
	}
}

插入排序

public static void sort(int[] a) {
	for (int low = 1; low < a.length; low++) {
		int t = a[low];
		int i = low - 1;
		// 自右向左找插入位置,如果比待插入元素大,则不断右移,空出插入位置
		while (i >= 0 && t < a[i]) {
			a[i + 1] = a[i];
			i--;
		}
		// 找到插入位置
		if (i != low - 1) {
			a[i + 1] = t;
		}
	}
}

归并排序

public static void sort(int[] a) {
	for (int low = 1; low < a.length; low++) {
		int t = a[low];
		int i = low - 1;
		// 自右向左找插入位置,如果比待插入元素大,则不断右移,空出插入位置
		while (i >= 0 && t < a[i]) {
			a[i + 1] = a[i];
			i--;
		}
		// 找到插入位置
		if (i != low - 1) {
			a[i + 1] = t;
		}
	}
}
public static void merge(int[] a1, int i, int iEnd, int j, int jEnd, int[] a2) {
	int k = i;
	while (i <= iEnd && j <= jEnd) {
		if (a1[i] < a1[j]) {
			a2[k] = a1[i];
			i++;
		} else {
			a2[k] = a1[j];
			j++;
		}
		k++;
	}
	if (i > iEnd) {
		System.arraycopy(a1, j, a2, k, jEnd - j + 1);
	}
	if (j > jEnd) {
		System.arraycopy(a1, i, a2, k, iEnd - i + 1);
	}
}

快速排序

public static void sort(int[] a) {
    quick(a, 0, a.length - 1);
}

private static void quick(int[] a, int left, int right) {
    if (left >= right) {
        return;
    }
    int p = partition(a, left, right);
    quick(a, left, p - 1);
    quick(a, p + 1, right);
}

/*
        注意事项
        1. 为啥要加内层循环的 i<j 条件
        2. 为啥要先处理 j,再处理 i
        3. 随机元素作为基准点
        4. 如果有大量重复元素
     */
private static int partition(int[] a, int left, int right) {
    int idx = ThreadLocalRandom.current().nextInt(right - left + 1) + left;
    // [0~9] right-left+1=3 [0,2]+4=[4,6]
    swap(a, idx, left);
    int pv = a[left];
    int i = left;
    int j = right;
    while (i < j) {
        // 1. j 从右向左找小(等)的
        while (i < j && a[j] > pv) {
            j--;
        }
        // 2. i 从左向右找大的
        while (i < j && a[i] <= pv) {
            i++;
        }
        // 3. 交换位置
        swap(a, i, j);
    }
    swap(a, left, i);
    return i;
}

private static void swap(int[] a, int i, int j) {
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
}

堆排序 (建堆,循环下潜)

public static void sort(int[] a) {
	heapify(a, a.length);
	for (int right = a.length - 1; right > 0; right--) {

		swap(a, 0, right);
		down(a, 0, right);
	}
}

// 建堆 O(n)
private static void heapify(int[] array, int size) {
	for (int i = size / 2 - 1; i >= 0; i--) {
		down(array, i, size);
	}
}

// 下潜
// leetcode 上数组排序题目用堆排序求解,非递归实现比递归实现大约快 6ms
private static void down(int[] array, int parent, int size) {
	while (true) {
		int left = parent * 2 + 1;
		int right = left + 1;
		int max = parent;
		if (left < size && array[left] > array[max]) {
			max = left;
		}
		if (right < size && array[right] > array[max]) {
			max = right;
		}
		if (max == parent) { // 没找到更大的孩子
			break;
		}
		swap(array, max, parent);
		parent = max;
	}
}

// 交换
private static void swap(int[] a, int i, int j) {
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

计数排序算法

public static void sort(int[] a) {
    // 1.循环数组获取最大值和最小值
    int max = a[0];
    int min = a[0];
    for (int i = 1; i < a.length; i++) {
        if (a[i] > max) {
            max = a[i];
        }
        if (a[i] < min) {
            min = a[i];
        }
    }
    // 2. 每个数组表示一个整数,每个元素进行计数
    int[] count = new int[max - min + 1];

    for (int v : a) { // v 原始数组元素 - 最小值 = count 索引
        count[v - min]++;
    }
    System.out.println(Arrays.toString(count));
    // 将计数完成的值,转换为排序好的数组
    int k = 0;
    for (int i = 0; i < count.length; i++) {
        // i + min 代表原始数组元素 count[i] 元素出现次数
        while (count[i] > 0) {
            a[k++] = i + min;
            count[i]--;
        }
    }
}

桶排序算法

 public static void sort(int[] ages) {
        // 1. 准备桶
        DynamicArray[] buckets = new DynamicArray[10];
        for (int i = 0; i < buckets.length; i++) {
            buckets[i] = new DynamicArray();
        }
        // 2. 放入年龄数据
        for (int age : ages) {
            buckets[age / 10].addLast(age);
        }
        int k = 0;
        int j = 0;
        for (DynamicArray bucket : buckets) {
            // 3. 排序桶内元素
            int[] array = bucket.array();
            InsertionSort.sort(array);
            System.out.println("桶[j]=>[" + j + "] " + Arrays.toString(array));
            // 4. 把每个桶排序好的内容,依次放入原始数组
            for (int v : array) {
                ages[k++] = v;
            }
            j++;
        }
    }

基数排序算法

public static void radixSort(String[] a, int length) {
        // 1. 准备桶
        ArrayList<String>[] buckets = new ArrayList[128];
        for (int i = 0; i < buckets.length; i++) {
            buckets[i] = new ArrayList<>();
        }
        // 2. 进行多轮按位桶排序
        for (int i = length - 1; i >= 0; i--) {
            // 将字符串放入合适的桶
            for (String s : a) {
                buckets[s.charAt(i)].add(s);
            }
            // 重新取出排好序的字符串,放回原始数组
            int k = 0;
            for (ArrayList<String> bucket : buckets) {
                for (String s : bucket) {
                    a[k++] = s;
                }
                bucket.clear();
            }
//            System.out.println(Arrays.toString(a));
        }
    }
posted @ 2025-04-27 10:38  陆陆无为而治者  阅读(23)  评论(0)    收藏  举报