冒泡排序
用Java实现冒泡排序,代码如下:
/**
* 冒泡排序:比较相邻的元素。如果第一个比第二个大,就交换他们两个。
* @param array 要排序的数组
* @return 排序号后的数组
*/
public static int[] BubbleSort(int[] array){
if(array == null){
throw new RuntimeException(" srcArray is null!");
}
int len = array.length;
for(int i=0; i<len-1; i++){
for(int j=0; j<len-i-1; j++){
if( array[j] > array[j+1]){
swap(array, j, j+1);
}
}
}
return array;
}
/**
* 交换数组指定位置的两个数
* @param src
* @param indexL
* @param indexR
*/
public static void swap(int[] src, int indexL, int indexR){
src[indexL] = src[indexL] ^ src[indexR];
src[indexR] = src[indexL] ^ src[indexR];
src[indexL] = src[indexL] ^ src[indexR];
}
测试数据:largeW.txt。由于信息量略大,故先选取前10,000和前100,000条数据进行测试,代码如下:
public static void main(String[] args) throws FileNotFoundException {
final String path = "C:\\sort";
//数据源
final String largeW = "largeW.txt";
//目标文件
final String largeW_bubble = "largeW_bubble.txt";
//要排序的数的个数
final int ARRAY_SIZE = 100000;
int [] array = new int[ARRAY_SIZE];
//开始时间
long startTime = System.currentTimeMillis();
Scanner sc = new Scanner(new File(path,largeW));
PrintWriter pw = new PrintWriter(new File(path,largeW_bubble));
int index = 0;
//读取数据 -> 数组
while(index<ARRAY_SIZE){
array[index] = sc.nextInt();
index++;
}
//冒一下泡
BubbleSort(array);
//将排序后数组写到文件中
for(int num : array){
pw.println(num);
}
pw.flush();
pw.close();
sc.close();
//结束时间
long endTime = System.currentTimeMillis();
System.err.printf("冒泡排序结束,共耗时:%d毫秒, 数据量:%d ", endTime-startTime, ARRAY_SIZE);
}
运行结果:
数据量为10,000时,运行时间是1.666秒
数据量为100,000时,运行时间是75.063秒
数据量为1000,000时,运行时间是:2.33小时...
归并排序
用Java实现归并排序,代码如下:
/**
* 归并排序
* @param src 要排序的数组
* @param des 排序后的数组
*/
public MergeSort(int[] src, int[] des){
//令初始化的子序列长度为1
int len = 1, n=src.length-1;
while( len<n){
//当归并的趟数为奇数时,归并排序的结果存储在des数组
MergerPass(src, des, n, len);
len *= 2;
//当归并的趟数为偶数时,归并排序的结果存储在src数组
MergerPass(des, src, n, len);
len *= 2;
}
}
/**
* 一趟归并
* @param src
* @param des
* @param n 待排序的数多少个
* @param len 子序列有多少个数
*/
public void MergerPass(int[] src, int[] des, int n, int len ){
//从数组的第二个位置开始存放待排序列,方便计算位置
int _p = 1;
//相邻的两个有序序列长度均为len,执行一次归并后指针_p前进2*len
while( _p <= (n-2*len+1) ){
Merge(src, des, _p, _p+len-1, _p+2*len-1);
_p += 2*len;
}
//相邻的两个有序序列长度分别为len和<len,执行一次归并后退出这趟归并
if( _p < (n-len+1) ){
Merge(src, des, _p, _p+len-1, n);
}
//只剩下一个子序列,将其copy到目标数组后退出这趟归并
else{
while(_p<=n){
des[_p] = src[_p];
_p++;
}
}
}
/**
* 一次归并
* @param src 待归并数组
* @param des 目标数组
* @param start 第一个个子序列的开始位置
* @param middle 第一个子序列的结束位置
* @param end 第二个子序列的结束位置
*/
public void Merge(int[] src, int[] des, int start, int middle, int end ){
// i指向第一个个子序列的首,j指向第二个子序列的首,k指向目标数组的首
int i = start, j = middle+1, k = start;
//比较两个子序列的数大小,将较小的数存到目标数组对应位置
while( i<=middle && j<=end ){
if( src[i] <= src[j]){
des[k++] = src[i++];
}else{
des[k++] = src[j++];
}
}
//收尾工作,将剩下的数全部存到目标数组
if( i<=middle ){
while( i<=middle ){
des[k++] = src[i++];
}
}else{
while( j<=end ){
des[k++] = src[j++];
}
}
}
public static void main(String[] args) throws FileNotFoundException {
final String path = "C:\\sort";
//数据源
final String largeW = "largeW.txt";
//目标文件
final String largeW_merge = "largeW_merge.txt";
//要排序的数的个数(注意!!! 第一个数不存放数据,为了方便计算。。。)
final int ARRAY_SIZE = 1000000+1;
int [] array = new int[ARRAY_SIZE];
int[] des = new int[ARRAY_SIZE];
Scanner sc = new Scanner(new File(path,largeW));
PrintWriter pw = new PrintWriter(new File(path,largeW_merge));
//注意!!! 归并排序的数组的第一个位置没有存放数
int index = 1;
//读取数据 -> 数组
while(index<ARRAY_SIZE){
array[index] = sc.nextInt();
index++;
}
//开始时间
long startTime = System.currentTimeMillis();
//归并排序
new MergeSort(array,des);
//结束时间
long endTime = System.currentTimeMillis();
System.err.printf("归并排序结束,共耗时:%d毫秒, 数据量:%d ", endTime-startTime, ARRAY_SIZE-1);
//将排序后数组写到文件中
for(int i=1; i<ARRAY_SIZE; i++){
pw.println(array[i]);
}
pw.flush();
pw.close();
sc.close();
}
运行结果:
数据量为10,000时,运行时间是:0.056秒!
数据量为100,000时,运行时间是:0.082秒!!
数据量为1000,000时,运行时间是:0.583秒!!!
总结冒泡排序和归并排序
冒泡排序:
走第一趟时扫描 n-1 个数,第二趟时扫描 n-2 个数...
时间复杂度是: O(n) = (n-1+1)*(n-1)/2 --> O(n) = n^2
归并排序:
每走一趟扫描 n 个数, 共走 log2n趟。
时间复杂度是: O(n) = n * log2n