排序算法
快速排序
单路快排
获取随机一个元素,元素左边是小于它的,元素右边是大于它的。
partition
:选择一个元素,交换left。比较nums[left]和nums[i],如果nums[i]<nums[left]
,找到一个小于标的元素的数据,交换到j的位置,j记录着最后一个小于标的元素的数据,切换j和left的位置,j所在的元素就是标的元素,返回j。获取left到right的随机一个索引,
new Random().nextInt(right - left + 1) + left;
。0-9随机一个数,是10的随机数。
public class QuickSort1 {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 5, 7, 4, 6};new QuickSort1().sort(nums);System.out.println(Arrays.toString(nums));}public void sort(int[] nums) {sort(nums, 0, nums.length - 1);}private void sort(int[] nums, int left, int right) {if (left >= right) {return;}int p = partition(nums, left, right);sort(nums, left, p - 1);sort(nums, p + 1, right);}private int partition(int[] nums, int left, int right) {int p = new Random().nextInt(right - left + 1) + left;swap(nums, p, left);int j = left;for (int i = left + 1; i <= right; i++) {if (nums[i] < nums[left]) {j++;swap(nums, i, j);}}swap(nums, left, j);return j;}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}
双路快排
如果小于标的元素,符合要求,p1++;大于标的元素,符合要求,p2–。
找到前面不满足要求的元素,将前面的大的元素和后面小的元素互换位置。
选择p2:
[left,p1-1]
是小于标的元素的,[p2+1,right]
是大于标的元素。选择p2就是选择小于标的元素的数据和标的元素互换。
public class QuickSort2 {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 5, 7, 4, 6};new QuickSort2().sort(nums);System.out.println(Arrays.toString(nums));}public void sort(int[] nums) {sort(nums, 0, nums.length - 1);}private void sort(int[] nums, int l, int r) {if (l >= r) {return;}int p = partition(nums, l, r);sort(nums, l, p - 1);sort(nums, p + 1, r);}private int partition(int[] nums, int l, int r) {int p = new Random().nextInt(r - l + 1) + l;swap(nums, l, p);int p1 = l + 1;int p2 = r;while (true) {//3 145672while (p1 <= p2 && nums[p1] < nums[l]) {p1++;}while (p1 <= p2 && nums[p2] > nums[l]) {p2--;}if (p1 >= p2) {break;}swap(nums, p1++, p2--);}swap(nums, l, p2);return p2;}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}
堆排序
用数组存储完全二叉树,parent(i)=(i-1)/2;左孩子是
2*i+1
,右孩子是2*1+2
。构建大顶堆。找到所有有左孩子或者有孩子的节点(
0-len / 2 - 1
),和它的左孩子、右孩子比较,将大的元素切换到根节点。继续处理以小的元素为根节点的子树。把大顶堆的最大元素放在数组最后,将数组之前的元素重新构建大顶堆。
public class HeapSort {public void sort(int[] nums) {buildHeap(nums, nums.length);for (int i