【Added by Light on 2014-07-27】
今天终于又来更新文章了,也是因为笔者上周忙的要死,又跟一群人去搞了搞课外活动,下面的代码又更新了一个快速排序法,确实很快,也确实耗CPU内存很多……
实测80000000随机数据排序,耗时4秒,CPU瞬间飙到28%.
/**************************************/
再一次贴出代码来,一是想激励一下自学的自己,再一个是想帮助需要的人,还有一个是希望有大神看到并不吝赐教。呵呵。。。
简单说明:
1.每种排序方法均封装在了一个单独的类中;
2.个人测试使用时,可在main中自己选择注释与解除注释来调用不同方法;
友情提示:个人测试时,千万不要用我的随机生成80000000个数的数组,用我下面那个注释掉的8个元素的数组就OK了。
另外,有个问题,希望看到文章的并有心看完的同仁发表下见解---->
我本机笔记本(Lenovo T440p 4GB - I5-4200M-2.50GHz )测试的排序效率:
冒泡:(本机实测:80万随即数据排序-->排序前:Fri Jul 18 18:20:27 CST 2014 排序前:Fri Jul 18 18:22:17 CST 2014)
选择:(本机实测:80万随机数据排序-->排序前:Fri Jul 18 19:56:43 CST 2014 排序前:Fri Jul 18 19:58:54 CST 2014)
插入:80000000万随机数据,1秒钟;
我确定用8个元素的数组都已经测试过了,排序方法是没有问题的,但是我很质疑插入排序方法的这个效率。
大家可以检查下我的代码,看哪里有问题没?
/**
* 展示各种排序方法:冒泡,选择,插入,快速排序法
* 排序方法均采用封装在类中的方式
* created by Light on 2014-7-18
*/
package com.second;
import java.util.*;
public class DoSorting {
public static void main(String[] args) {
// TODO Auto-generated method stub
//随机产生一个长度为80000的数据,这里先产生整数数组
//int a = 800000;
int [] arr = new int[80000000];
//int arr[] = {0,-1,2,4,-6,33,10,11};
//初始化数组,使用for循环
for(int i=0;i<arr.length;i++)
{
arr[i] = (int)Math.random()*100000;
}
//使用冒泡法排序
//Bubble b = new Bubble();
//使用选择法
//Selection s = new Selection();
//插入法
//Insertion it = new Insertion();
//快速排序法
QuickSort qc = new QuickSort();
//排序之前打印系统时间
//Calendar c = Calendar.getInstance();
//Date d = new Date();
System.out.println("排序前:"+ new Date());
//调用排序
//冒泡
//b.sort(arr);
//b.showArray(arr);
//选择
//s.sort(arr);
//s.showArray(arr);
//插入
//it.sort(arr);
//it.showArray(arr);
//快速
qc.sort(0, arr.length-1, arr);
//qc.showArray(arr);
//排序之后打印系统时间
System.out.println("排序前:"+ new Date());
}
}
//冒泡法类
class Bubble
{
//Define public function directly
public void sort(int arr[]) //using Array as kind of reference
{
for(int i=0;i<arr.length-1;i++)//外层循环控制轮询比较回合
{
//内层循环控制每个回合中的比较范围,没完成一个回合,范围应该减小一个元素
//因为上一轮已经保证最大的排在了最后
for(int j=0;j<arr.length-1-i;j++)
{
int temp = 0;
//判断大小
if(arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
//提供打印数组的方法
public void showArray(int arr[])
{
System.out.print("数组排序后为:");
//for循环打印
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
//选择法类
class Selection
{
//直接创建选择方法
public void sort(int arr[])
{
//外层循环控制回合数,每一个回合都把最小的一个数与arr[i]交换
for(int i=0;i<arr.length-1;i++)
{
//内存循环保证每个回合,即每一次内层循环退出时,找到一个最小值
int minArr = arr[i];
int minIndex = i;
int temp =0 ;
for(int j=i+1;j<arr.length;j++)
{
//判断所去元素与minArr的大小,如果arr[j]比minArr小,则两者交换位置,否则不做处理
if(arr[j]<minArr)
{
minArr = arr[j];
minIndex = j;
}
}//当循环退出时,minArr保证是本轮比较数组中最小的一个数
temp = arr[i];
arr[i] = minArr;
arr[minIndex] = temp;
}
}
//showArray
public void showArray(int arr[])
{
System.out.print("数组排序后为:");
//for循环打印
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
//插入法类
class Insertion
{
//直接创建插入方法
public void sort(int arr[])
{
//外层循环保证-->从第二个元素开始,一直到最后一个数-->进入内层处理逻辑,即在前面找到自己合适的位置
for(int i=1;i<arr.length;i++)
{
int tempArr = arr[i];
//int minArr = arr[i-1];
int minIndex = i-1;
while(minIndex>=0 && arr[minIndex] > tempArr)
{
arr[minIndex+1]=arr[minIndex];
minIndex--;
}//内层循环退出,表示找为arr[i]到了合适的位置,即arr[minIndex+1]
//需要把tempArr赋给前面空出来的位置
arr[minIndex+1] = tempArr;
}
}
//showArray
public void showArray(int arr[])
{
System.out.print("数组排序后为:");
//for循环打印
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
//快速查询法
class QuickSort
{
//定义sort方法
public void sort(int left,int right, int array[])
{
int l = left;
int r = right;
int pivot = array[(left+right)/2];
int tempArray = 0;//后面做交换使用
while(l<r)//大的条件是l<r,即左边界要小于右边界
{
//内层分隔处理,左右各自处理
while(array[l]<pivot) {l++;}
while(array[r]>pivot) {r--;}
//如果在上面两个循环退出时,l>=r,则表示pivot的左边都比pivot小,右边都比pivot大,此轮排序目的达到,即将array分为两部分
if(l>=r) break;
//如果上面条件不成立,则将上面while循环找出的不符合条件的左右元素对调,目的也是向把array分为两部分靠拢
tempArray = array[l];
array[l] = array[r];
array[r] = tempArray;
//有可能存在array[l] or array[r]正好就是pivot,此时可在对调之后直接越过此元素,此时可以返回顶层while去检查l<r是否为true
if(array[l]==pivot) {r--;}
if(array[r]==pivot) {l++;}
}
//如果while退出,此时返回l=r,为了保证这个值不再参与排序,同样要保证能进入递归,需要将l and r 都处理一下
if(l==r)
{
l++;
r--;
}
//到此,第一轮的排序(分组)就完成了,将原array分为三部分--> array[0]~array[r] , array[l]~array[length-1]和array[l-1]不动元素
//并且,array[0]~array[r] 均小于array[l-1]; array[l]~array[length-1] 均大于 array[l-1]
//下面调用本身,实现上面逻辑的递归,只是入参会适当修改
if(r>left) {sort(left, r, array);}
if(l<right) {sort(l, right, array);}
}
//定义showArray方法
public void showArray(int arr[])
{
System.out.print("数组排序后为:");
//for循环打印
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
System.out.println();
}
}