在用分而治之算法写归并排序的时候,有这么一个步骤,把问题化小,一直划到问题很esay解决的地步,
//对左边一半进行递归
mergerSort(a, low, mid, b);
//对右一边进行递归,一直递归到每一个数字就占用一个表为止
mergerSort(a, mid + 1, high, b); //进行归并
merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
我的问题是:左递归和右递归之前和之后,a数组里面的元素的位置发生了什么变化,他们不还都存储a数组里面吗?而且他们的位置也没有变化吧,只是几个指针对着数组的索引走来走去?这样理解对嘛,但如果把左递归和右递归去掉,程序排序不成了
[size=24px]看程序[/size]
package algorithm;/* 分治法——归并排序
二路归并排序的分治策略是:
(1)划分:将待排序序列r1, r2, …, rn划分为两个长度相等的子序列r1, …, rn/2和rn/2+1, …, rn;
(2)求解子问题:分别对这两个子序列进行排序,得到两个有序子序列;
(3)合并:将这两个有序子序列合并成一个有序序列。*/
public class Test1 {
static int count;
public static void main(String[] args) {
int a[] = { 25,14,53,32,64,45,32,78 };// 这里对8个元素进行排序
int low = 0, high = 7;// 初始化low和high的值,即数组的起始和终止的坐标
// 辅助数组b,作为临时数组
int b[] = new int[a.length];
//输出排序前的数组
System.out.print("排序前:");
for (int i = 0; i <= high; i++) {
System.out.print(a[i] + " ");
}
// 归并排序
mergerSort(a, low, high, b);
//输出排序后的数组
System.out.print("排序后:");
for (int i = 0; i <= high; i++) {
System.out.print(a[i] + " ");
}
}
/**
* 分治和归并
*/
public static void mergerSort(int a[], int low, int high, int b[]) {
int mid = 0;
count++;
//如果序列中只有0个或1个记录,就不用排序啦
if (low < high) {
mid = (high + low) / 2;// 分治位置,即将数组拆分的位置
//对左边一半进行递归
mergerSort(a, low, mid, b); //一直分,分到一个数字,占一个串
/*
* 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
* */
//对右边一半进行递归
mergerSort(a, mid + 1, high, b); //一直分,分到一个数字,占一个串
//进行归并
merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
}
}
/**
一次归并
*/
public static void merger(int[] a, int low, int mid, int high, int b[]) {
//左子串的起始位置
int i = low;
//右子串的起始位置
int j = mid + 1;
int p = 0;
// 合并两个有序数组 子序列1 a[low..mid] 子序列2 a[mid+1..high]
while (i <= mid && j <= high) { //任何一个子序列到头了,都停止循环
b[p++] = (a[i] <= a[j]) ? a[i++] : a[j++]; //都往后面移动一位
}
// 如果子序列1没有合并完则直接复制到复制数组中去
while (i <= mid) {
b[p++] = a[i++];
}
// 如果子序列2没有合并完则直接复制到复制数组中去
while (j <= high) {
b[p++] = a[j++];
}
// 把辅助数组的元素复制到原来的数组中去
for (p = 0, i = low; i <= high; i++, p++) {
a[i] = b[p];
}
}
} 算法分而治之归并排序,递归
//对左边一半进行递归
mergerSort(a, low, mid, b);
//对右一边进行递归,一直递归到每一个数字就占用一个表为止
mergerSort(a, mid + 1, high, b); //进行归并
merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
我的问题是:左递归和右递归之前和之后,a数组里面的元素的位置发生了什么变化,他们不还都存储a数组里面吗?而且他们的位置也没有变化吧,只是几个指针对着数组的索引走来走去?这样理解对嘛,但如果把左递归和右递归去掉,程序排序不成了
[size=24px]看程序[/size]
package algorithm;/* 分治法——归并排序
二路归并排序的分治策略是:
(1)划分:将待排序序列r1, r2, …, rn划分为两个长度相等的子序列r1, …, rn/2和rn/2+1, …, rn;
(2)求解子问题:分别对这两个子序列进行排序,得到两个有序子序列;
(3)合并:将这两个有序子序列合并成一个有序序列。*/
public class Test1 {
static int count;
public static void main(String[] args) {
int a[] = { 25,14,53,32,64,45,32,78 };// 这里对8个元素进行排序
int low = 0, high = 7;// 初始化low和high的值,即数组的起始和终止的坐标
// 辅助数组b,作为临时数组
int b[] = new int[a.length];
//输出排序前的数组
System.out.print("排序前:");
for (int i = 0; i <= high; i++) {
System.out.print(a[i] + " ");
}
// 归并排序
mergerSort(a, low, high, b);
//输出排序后的数组
System.out.print("排序后:");
for (int i = 0; i <= high; i++) {
System.out.print(a[i] + " ");
}
}
/**
* 分治和归并
*/
public static void mergerSort(int a[], int low, int high, int b[]) {
int mid = 0;
count++;
//如果序列中只有0个或1个记录,就不用排序啦
if (low < high) {
mid = (high + low) / 2;// 分治位置,即将数组拆分的位置
//对左边一半进行递归
mergerSort(a, low, mid, b); //一直分,分到一个数字,占一个串
/*
* 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
* */
//对右边一半进行递归
mergerSort(a, mid + 1, high, b); //一直分,分到一个数字,占一个串
//进行归并
merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
}
}
/**
一次归并
*/
public static void merger(int[] a, int low, int mid, int high, int b[]) {
//左子串的起始位置
int i = low;
//右子串的起始位置
int j = mid + 1;
int p = 0;
// 合并两个有序数组 子序列1 a[low..mid] 子序列2 a[mid+1..high]
while (i <= mid && j <= high) { //任何一个子序列到头了,都停止循环
b[p++] = (a[i] <= a[j]) ? a[i++] : a[j++]; //都往后面移动一位
}
// 如果子序列1没有合并完则直接复制到复制数组中去
while (i <= mid) {
b[p++] = a[i++];
}
// 如果子序列2没有合并完则直接复制到复制数组中去
while (j <= high) {
b[p++] = a[j++];
}
// 把辅助数组的元素复制到原来的数组中去
for (p = 0, i = low; i <= high; i++, p++) {
a[i] = b[p];
}
}
} 算法分而治之归并排序,递归
/*
* 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
* */
//对右边一半进行递归
mergerSort(a, mid + 1, high, b); 在递归的时候并没有对数组赋值,移位的什么操作,怎么就各自排好序了呢
mergerSort(a, low, mid, b); //一直分,分到一个数字,占一个串
/*
* 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
* */
//对右边一半进行递归
mergerSort(a, mid + 1, high, b); //一直分,分到一个数字,占一个串
//进行归并
merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
这里面的3个递归方法,什么时候第一个递归结束,什么时候第二个递归结束,?