获取随机一个元素,元素左边是小于它的,元素右边是大于它的。
partition
:选择一个元素,交换left。比较nums[left]和nums[i],如果nums[i]
,找到一个小于标的元素的数据,交换到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 145672
while (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