生成测试用数据
@Test
public void generatePhoneNum() throws Exception {
generatePhoneNum(50000);
generatePhoneNum(100000);
generatePhoneNum(150000);
generatePhoneNum(200000);
generatePhoneNum(250000);
}
public void generatePhoneNum(int count) throws Exception {
BufferedWriter bw =
new BufferedWriter(new FileWriter(new File("/Users/xxxxx/Desktop/phone" + count + ".txt")));
for (int i = 0; i < count; i++) {
bw.write(eleven());
if (i != count - 1) {
bw.newLine();
}
}
bw.close();
}
private Random random = new Random();
private String eleven() {
StringBuilder sb = new StringBuilder("1");
for (int i = 0; i < 9; i++) {
sb.append(random.nextInt(10));
}
return sb.toString();
}
由此生成了5
个待测试数据样本,分别有50,000
、100,000
、150,000
、200,000
、250,000
个int
值
每个int
值长度为10
,以1
为首(模拟电话号码,但因为int
只能装2,147,483,647
,所以没使用11
位,但又懒得改为long
类型,聚焦在对比数据即可)。
时间复杂度为O(n2)
的排序
@Test
public void sortTest() throws Exception {
int count = 50000;
// sortTest(count, "selection");
// sortTest(count, "bubble");
// sortTest(count, "insertion");
}
public void sortTest(int count, String sortType) throws Exception {
int[] sort = new int[count];
Scanner scanner = new Scanner(new File("/Users/xxxxx/Desktop/phone" + count + ".txt"));
int i = 0;
while (scanner.hasNext()) {
sort[i] = scanner.nextInt();
i++;
}
long start = System.currentTimeMillis();
if ("selection".equals(sortType)) {
selectionSort(sort, count);
} else if ("bubble".equals(sortType)) {
bubbleSort(sort, count);
} else if ("insertion".equals(sortType)) {
insertionSort(sort, count);
}
long stop = System.currentTimeMillis();
System.out.println("数组长度" + count);
System.out.println(sortType + "排序耗时" + (stop - start) + "毫秒");
}
// 数组长度 选择排序 冒泡排序 插入排序
// 50,000 1,836 4,862 275
// 100,000 6,726 18,813 1,118
// 150,000 14,806 42,590 2,297
// 200,000 26,529 74,957 4,070
// 250,000 40,677 118,969 6,448
不是平均值,只跑了一遍,主要关注插入排序和其他两个排序相比,真是太优秀了
时间复杂度为O(nlogn)
的排序
@Test
public void sortTest() throws Exception {
int count = 50000;
// sortTest(count, "selection");
// sortTest(count, "bubble");
// sortTest(count, "insertion");
// sortTest(count, "merge");
sortTest(count, "quick");
}
public void sortTest(int count, String sortType) throws Exception {
int[] sort = new int[count];
Scanner scanner = new Scanner(new File("/Users/xuxuesong/Desktop/phone" + count + ".txt"));
int i = 0;
while (scanner.hasNext()) {
sort[i] = scanner.nextInt();
i++;
}
long start = System.currentTimeMillis();
if ("selection".equals(sortType)) {
selectionSort(sort, count);
} else if ("bubble".equals(sortType)) {
bubbleSort(sort, count);
} else if ("insertion".equals(sortType)) {
insertionSort(sort, count);
} else if ("merge".equals(sortType)) {
mergeSort(sort, count);
} else if ("quick".equals(sortType)) {
quickSort(sort, count);
}
long stop = System.currentTimeMillis();
System.out.println("数组长度" + count);
System.out.println(sortType + "排序耗时 " + (stop - start) + " 毫秒");
}
// 数组长度 选择排序 冒泡排序 插入排序 归并排序 快速排序
// 50,000 1,836 4,862 275 1,678 21
// 100,000 6,726 18,813 1,118 3,339 21
// 150,000 14,806 42,590 2,297 8,280 22
// 200,000 26,529 74,957 4,070 12,793 26
// 250,000 40,677 118,969 6,448 13,469 40
// 1,000,000 364,153 91
// 5,000,000 455
// 数组长度 选择排序 冒泡排序 插入排序 归并排序 快速排序
// 50,000 1,836 4,862 275 20 21
// 100,000 6,726 18,813 1,118 40 21
// 150,000 14,806 42,590 2,297 33 22
// 200,000 26,529 74,957 4,070 56 26
// 250,000 40,677 118,969 6,448 89 40
// 1,000,000 175 91
// 5,000,000 832 455
// 50,000,000 9,151 5,332
快速排序这速度…
测试结果中,归并排序走了个弯路,临时数组之前我是用temp = new int[array.length]
来完成的,每次都要找一个连续内存的很大的数组,时间全浪费在这儿了。对不起,归并排序。
时间复杂度为O(n)
的排序
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Random;
import java.util.Scanner;
import org.junit.Test;
public class RadixSortTest {
public void mergeSort(int[] array, int length) {
mergeSort(array, 0, length - 1);
}
private void mergeSort(int[] array, int left, int right) {
if (left >= right) {
return;
}
int mid = left + ((right - left) >> 1);
mergeSort(array, left, mid);
mergeSort(array, mid + 1, right);
merge(array, left, mid, right);
}
private void merge(int[] array, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int leftPos = left;
int rightPos = mid + 1;
int tempPos = 0;
while (leftPos <= mid && rightPos <= right) {
if (array[leftPos] <= array[rightPos]) {
temp[tempPos++] = array[leftPos++];
} else {
temp[tempPos++] = array[rightPos++];
}
}
while (leftPos <= mid) {
temp[tempPos++] = array[leftPos++];
}
while (rightPos <= right) {
temp[tempPos++] = array[rightPos++];
}
for (int i = 0; i < temp.length; i++) {
array[left + i] = temp[i];
}
}
public void quickSort(int[] array, int length) {
quickSort(array, 0, length - 1);
}
public void quickSort(int[] array, int left, int right) {
if (left >= right) {
return;
}
int partition = partition(array, left, right);
quickSort(array, left, partition - 1);
quickSort(array, partition + 1, right);
}
public int partition(int[] array, int left, int right) {
int partitionPos = left;
int partition = array[right];
for (int i = left; i < right; i++) {
if (array[i] <= partition) {
int temp = array[i];
array[i] = array[partitionPos];
array[partitionPos] = temp;
partitionPos++;
}
}
array[right] = array[partitionPos];
array[partitionPos] = partition;
return partitionPos;
}
public void radixSort(int[] array, int length) {
int numLength = (array[0] + "").length();
for (int i = 0; i < numLength; i++) {
radixSort(array, length, i);
}
}
private void radixSort(int[] array, int length, int index) {
int pow = (int) Math.pow(10, index);
// 求最大值
int max = array[0] / pow % 10;
for (int i = 1; i < length; i++) {
int item = array[i] / pow % 10;
if (max < item) {
max = item;
}
}
int[] tempArray = new int[max + 1];
for (int i = 0; i < array.length; i++) {
int item = array[i] / pow % 10;
tempArray[item] = tempArray[item] + 1;
}
for (int i = 1; i < tempArray.length; i++) {
tempArray[i] = tempArray[i] + tempArray[i - 1];
}
int[] result = new int[length];
for (int i = length - 1; i >= 0; i--) {
int item = array[i] / pow % 10;
result[tempArray[item] - 1] = array[i];
tempArray[item] = tempArray[item] - 1;
}
for (int i = 0; i < length; i++) {
array[i] = result[i];
}
}
@Test
public void generatePhoneNum() throws Exception {
// generatePhoneNum(100000);
// generatePhoneNum(200000);
// generatePhoneNum(500000);
// generatePhoneNum(1000000);
// generatePhoneNum(5000000);
// generatePhoneNum(50000000);
}
public void generatePhoneNum(int count) throws Exception {
BufferedWriter bw =
new BufferedWriter(new FileWriter(new File("/Users/xuxuesong/Desktop/phone" + count + ".txt")));
for (int i = 0; i < count; i++) {
bw.write(eleven());
if (i != count - 1) {
bw.newLine();
}
}
bw.close();
}
private Random random = new Random();
private String eleven() {
StringBuilder sb = new StringBuilder("1");
for (int i = 0; i < 9; i++) {
sb.append(random.nextInt(10));
}
return sb.toString();
}
@Test
public void sortTest() throws Exception {
int count = 500000000;
// sortTest(count, "merge");
// sortTest(count, "quick");
sortTest(count, "radix");
}
public void sortTest(int count, String sortType) throws Exception {
int[] sort = new int[count];
Scanner scanner = new Scanner(new File("/Users/xuxuesong/Desktop/phone" + count + ".txt"));
int i = 0;
while (scanner.hasNext()) {
sort[i] = scanner.nextInt();
i++;
}
long start = System.currentTimeMillis();
if ("merge".equals(sortType)) {
mergeSort(sort, count);
} else if ("quick".equals(sortType)) {
quickSort(sort, count);
} else if ("radix".equals(sortType)) {
radixSort(sort, count);
}
long stop = System.currentTimeMillis();
System.out.println("数组长度" + count);
System.out.println(sortType + "排序耗时 " + (stop - start) + " 毫秒");
}
// 数组长度 归并排序 快速排序 基数排序
// 100,000 24 14 43
// 200,000 45 28 71
// 500,000 153 89 149
// 1,000,000 162 95 175
// 5,000,000 886 491 738
// 50,000,000 10,570 5,590 8,660
}
不过这个结果,有点儿接受不了
其实基数排序还可以继续优化
而且受限于物理机的配置,数据量只能搞到千万级别,再高玩儿不了了
可以看出,一般情况下,快排就可以很好的解决问题了