import java.util.Arrays;
import java.util.Random;
/**
* Filename: Class3FenZhiFa.java Description:
* 使用分治法排序(将数组进行二分拆解,二分拆完再二分直至不能拆,然后进行排序)
* @author: guzhangyan
* @date: 2018年8月3日 上午11:40:28
*/
public class Class3FenZhiFa {
public static void main(String[] args) {
int[] shuZu = new int[1000000];
Random random = new Random();
for (int i = 0; i < shuZu.length; i++) {
shuZu[i] = random.nextInt(1000);
}
fenZhiFaSort(shuZu, 0, shuZu.length - 1);
for (int i = 1; i < shuZu.length; i++) {
if (shuZu[i] - shuZu[i - 1] < 0) {
System.out.println(i);
}
}
System.out.println(Arrays.toString(shuZu));
}
private static void fenZhiFaSort(int[] shuZu, int start, int end) {
if (end == start) {
return;
}
// 先拆成两部分进行排序
fenZhiFaSort(shuZu, start, (start + end) / 2);
fenZhiFaSort(shuZu, (start + end) / 2 + 1, end);
int thisNum = 0;
int startKey = start;
// 依次取后半部分数值,和前半部分依次比较,因为两部分都是拍过序的,所以真实比较次数很少
// 后半部分下标为i,前半部分为startKey,如果后半部分的值比前者小,则把后半部分值移到前面,startKey及之后的值依次后移(后移的操作比较占时间,比较操作不多)
for (int i = (start + end) / 2 + 1; i <= end && startKey < i;) {
thisNum = shuZu[i];
if (thisNum < shuZu[startKey]) {
for (int j = i; j > startKey; j--) {
shuZu[j] = shuZu[j - 1];
}
shuZu[startKey] = thisNum;
i++;
startKey++;
} else {
//如果前者小,则不需要动,前者后一个进行比较
startKey++;
}
}
}
}
排序一百万条数据,合并排序78.137s,冒泡排序1268.768s。
优化合并排序
将合并时候的操作,换个方式排序100w数据时间为200毫秒左右,一亿条数据为13.079s
因为T(n) = 2T(n/2) + n;复杂度是o(n*lgn);
而上一个方式为 T(n) = 2T(n/2) + n*n/2;复杂度为n*n;
/**
* @param shuZu
* @param start
* @param end
* @author: guzhangyan
* @version:2018年8月6日 上午9:27:33 与分治法1不一样的是:进行排序时候,是直接排序,而非移动式
*/
private static void fenZhiFaSort2(int[] shuZu, int start, int end) {
if (end == start) {
return;
}
if (end - start < 100) {// 当函数长度较短时,还是使用方法一合适
// 先拆成两部分进行排序
fenZhiFaSort(shuZu, start, (start + end) / 2);
fenZhiFaSort(shuZu, (start + end) / 2 + 1, end);
} else {
// 先拆成两部分进行排序
fenZhiFaSort2(shuZu, start, (start + end) / 2);
fenZhiFaSort2(shuZu, (start + end) / 2 + 1, end);
}
int startKey1 = start;
int startKey2 = (start + end) / 2 + 1;
int[] newShuZu = new int[end - start + 1];
int newKey = 0;
while (true) {
if (startKey1 > (start + end) / 2 && startKey2 > end) {
break;
}
if (startKey1 > (start + end) / 2) {
newShuZu[newKey] = shuZu[startKey2];
startKey2++;
newKey++;
continue;
}
if (startKey2 > end) {
newShuZu[newKey] = shuZu[startKey1];
startKey1++;
newKey++;
continue;
}
if (shuZu[startKey2] > shuZu[startKey1]) {
newShuZu[newKey] = shuZu[startKey1];
startKey1++;
newKey++;
continue;
} else {
newShuZu[newKey] = shuZu[startKey2];
startKey2++;
newKey++;
continue;
}
}
for (int i = 0; i < newShuZu.length; i++) {
shuZu[start + i] = newShuZu[i];
}
}