归并排序(递归)
public class Test {
public void mergeSort(int[] nums, int low, int high)
{
if (low >= high) return;
int mid = low + ((high - low) >> 1);
mergeSort(nums, low, mid);
mergeSort(nums, mid + 1, high);
merge(nums, low, mid, high);
}
private void merge(int[] nums, int low, int mid, int high)
{
int[] temp = Arrays.copyOfRange(nums, low, high + 1);
int n1 = low, n2 = mid + 1, index = low;
while (n1 <= mid && n2 <= high)
{
if (temp[n1 - low] <= temp[n2 - low])
{
nums[index] = temp[n1 - low];
n1++;
}
else
{
nums[index] = temp[n2 - low];
n2++;
}
index++;
}
while (n1 <= mid)
{
nums[index] = temp[n1 - low];
index++;
n1++;
}
/*while (n2 <= high)
{
nums[index] = temp[n2 - low];
index++;
n2++;
}这里可以去掉,因为第二段数组内容已经提前拷贝过去了*/
}
public static void main(String[] args){
int[] nums = new int[]{1,3,1,3,2,4,5,8,9,4,5,6,1,4,1,9,8,4,8,6,1,1,6,1,2,5,6,1,4,5,8,4,1};
new Test().mergeSort(nums, 0, nums.length - 1);
for (int num : nums)
{
System.out.printf("%d ", num);
}
}
}
关键点在于merge的时候要开一个辅助数组用于存储归并结果,也可以直接拷贝原始数组的那一段,参照拷贝后的数组对原始数组进行归并。
归并排序(非递归)
public class Test {
private int[] nums;
private int[] buffer;
public static void main(String[] args){
int[] test = new int[]{15,6,1,5,6,8,1,4,5,6,13,2,4,7,8,1,46,5,1,3,249,86,136,4,613,24,9,84,16,5,15,6,132};
new Test(test).mergeSort();
for (int num : test)
{
System.out.print(num + " ");
}
}
public Test(int[] nums)
{
this.nums = nums;
this.buffer = new int[nums.length];
}
private void mergeSort()
{
int size = 1;
while (size <= nums.length)
{
for (int i = 0;i + size <= nums.length;i += (size << 1))
{ //保证至少划分一块
int low = i, mid = i + size - 1;
int high = Math.min(i + (size << 1) - 1, nums.length - 1);
//保证第二块的下标正确
merge(low, mid, high);
}
size <<= 1;
}
}
private void merge(int low, int mid, int high)
{
System.arraycopy(nums, low, buffer, low, high - low + 1);
int index1 = low, index2 = mid + 1;
int index = low;
while (index1 <= mid && index2 <= high)
{
if (buffer[index1] <= buffer[index2])
{
nums[index] = buffer[index1];
index1++;
}
else
{
nums[index] = buffer[index2];
index2++;
}
index++;
}
while (index1 <= mid)
{
nums[index] = buffer[index1];
index1++;
index++;
}
}
}
堆排序(非优先队列)
public class Test {
private final int[] nums;
public static void main(String[] args){
int[] test = new int[]{15,6,1,5,6,8,1,4,5,6,13,2,4,7,8,1,46,5,1,3,249,86,136,4,613,24,9,84,16,5,15,6,132};
new Test(test).heapSort();
for (int num : test)
{
System.out.print(num + " ");
}
}
public Test(int[] nums)
{
this.nums = nums;
}
private void heapSort()
{
for (int i = ((nums.length >> 1) - 1);i >= 0;i--)
{
adjustHeap(i, nums.length - 1);
}//从第一个非叶节点开始
for (int i = nums.length - 1;i > 0;i--)
{
swap(0, i);
adjustHeap(0, i - 1);
//规模减小1个节点
}
}
private void swap(int indexA, int indexB)
{
int temp = nums[indexA];
nums[indexA] = nums[indexB];
nums[indexB] = temp;
}
private void adjustHeap(int low, int high)
{
int temp = nums[low];//保存父亲节点以备交换
for (int i = ((low << 1) + 1);i <= high;i = ((i << 1) + 1))
{
if (i + 1 <= high && nums[i] < nums[i + 1]) i++;
//比较左右子节点
if (temp > nums[i]) break;
//如果后续节点已经合法,则不再调整
nums[low] = nums[i];
//直接赋值
low = i;
//接着调整后续子节点
}
nums[low] = temp;
//最后完成交换
}
}