首先:咱也借用一下网上的那张XXX的图,咯!在下面:
接下来,就是咱的验证时间了(验证什么?当然是各种算法的时间复杂度咯),没什么好说的了,直接上码吧。
代码实现:
import java.util.Arrays;
public class SortSummary {
/**
* 各排序算法效率比较
*/
// 1、冒泡排序
int[] bubbleSort(int[] data) {
for (int i = 1; i < data.length; i++) {
for (int j = 0; j < data.length - i; j++) {
if (data[j] > data[j + 1]) {
int temp = data[j + 1];
data[j + 1] = data[j];
data[j] = temp;
}
}
}
return data;
}
// 2、快速排序
int[] quickSort(int[] data, int start, int end) {
int tstart = start;
int tend = end;
int base = data[tstart];
while (tstart < tend) {
while (tstart < tend && data[tend] >= base) {
tend--;
}
if (data[tend] < base) {
int temp = data[tstart];
data[tstart] = data[tend];
data[tend] = temp;
}
while (tstart < tend && data[tstart] <= base) {
tstart++;
}
if (data[tstart] > base) {
int temp = data[tend];
data[tend] = data[tstart];
data[tstart] = temp;
}
}
if (tstart > start) {
quickSort(data, start, tstart - 1);
}
if (tend < end) {
quickSort(data, tend + 1, end);
}
return data;
}
// 3、选择排序
int[] selectSort(int[] data) {
for (int i = 0; i < data.length - 1; i++) {
int index = i;
for (int j = i + 1; j < data.length; j++) {
if (data[j] < data[index]) {
index = j;
}
}
int temp = data[i];
data[i] = data[index];
data[index] = temp;
}
return data;
}
// 4、堆排序
void heapSortUtil1(int[] data, int root, int size) {
int rootNode = root;
int leftNode = 2 * rootNode + 1;
int rightNode = 2 * rootNode + 2;
if (leftNode <= size) {
if (data[rootNode] < data[leftNode]) {
rootNode = leftNode;
}
}
if (rightNode <= size) {
if (data[rootNode] < data[rightNode]) {
rootNode = rightNode;
}
}
if (rootNode != root) {
int temp = data[root];
data[root] = data[rootNode];
data[rootNode] = temp;
heapSortUtil1(data, rootNode, size);
}
}
void heapSortUtil2(int[] data, int size) {
for (int i = size; i >= 0; i--) {
heapSortUtil1(data, i, size);
}
}
int[] heapSort(int[] data) {
for (int i = 0; i < data.length; i++) {
heapSortUtil2(data, data.length - i - 1);
int temp = data[0];
data[0] = data[data.length - i - 1];
data[data.length - i - 1] = temp;
}
return data;
}
// 5、插入排序
int[] insertSort(int[] data) {
for (int i = 1; i < data.length; i++) {
int index = data[i];
int j = i;
for (j -= 1; j >= 0 && index < data[j]; j--) {
data[j + 1] = data[j];
}
data[j + 1] = index;
}
return data;
}
// 6、希尔排序
int[] shellSort(int[] data) {
for(int k=data.length/2;k>0;k/=2){
for (int i = k; i < data.length; i++) {
int index = data[i];
int j = i;
for (j -= k; j >= 0 && index < data[j]; j-=k) {
data[j + k] = data[j];
}
data[j + k] = index;
}
}
return data;
}
//7、归并排序
void mergeArray(int[] data,int start,int mid,int end){
int[] temp=new int[end-start+1];
int s=start;
int e=mid+1;
int k=0;
while(s<=mid&&e<=end){
if(data[s]<data[e]){
temp[k++]=data[s++];
}else{
temp[k++]=data[e++];
}
}
while(s<=mid){
temp[k++]=data[s++];
}
while(e<=end){
temp[k++]=data[e++];
}
for(int i=0;i<temp.length;i++){
data[start+i]=temp[i];
}
}
int[] mergeSort(int[] data,int start,int end){
int mid=(end-start)/2+start;
if(start<end){
mergeSort(data,start,mid);
mergeSort(data,mid+1,end);
mergeArray(data,start,mid,end);
}
return data;
}
//主方法main
public static void main(String[] args) {
// 各排序算法效率比较
int n=10000;//数据的个数
long start;// 记录算法开始的时间
long end;// 记录算法结束的时间
SortSummary ss = new SortSummary();
int[] data = new int[n];
// 随机生成10000个序列保存于数组中
for (int i = 0; i < n; i++) {
data[i] = (int) (Math.random() * 10000);
}
int[] data1=new int[n];
int[] data2=new int[n];
int[] data3=new int[n];
int[] data4=new int[n];
int[] data5=new int[n];
int[] data6=new int[n];
int[] data7=new int[n];
//复制数组,java中对数组的复制只能是System.arraycopy
System.arraycopy(data, 0, data1, 0, n);
System.arraycopy(data, 0, data2, 0, n);
System.arraycopy(data, 0, data3, 0, n);
System.arraycopy(data, 0, data4, 0, n);
System.arraycopy(data, 0, data5, 0, n);
System.arraycopy(data, 0, data6, 0, n);
System.arraycopy(data, 0, data7, 0, n);
System.out.println(Arrays.toString(data));
//------------------------------------------------------------------
// 1、冒泡排序
start = System.currentTimeMillis();
data1 = ss.bubbleSort(data1);
end = System.currentTimeMillis();
//System.out.println(Arrays.toString(data1));
System.out.println("冒泡排序 用时:" + (end - start));
// 2、快速排序
start = System.currentTimeMillis();
data2 = ss.quickSort(data2, 0, data.length - 1);
end = System.currentTimeMillis();
// System.out.println(Arrays.toString(data2));
System.out.println("快速排序 用时:" + (end - start));
// 3、选择排序
start = System.currentTimeMillis();
data3 = ss.selectSort(data3);
end = System.currentTimeMillis();
// System.out.println(Arrays.toString(data3));
System.out.println("选择排序 用时:" + (end - start));
// 4、堆排序
start = System.currentTimeMillis();
data4= ss.heapSort(data4);
end = System.currentTimeMillis();
// System.out.println(Arrays.toString(data4));
System.out.println("堆排序 用时:" + (end - start));
// 5、插入排序
start = System.currentTimeMillis();
data5 = ss.insertSort(data5);
end = System.currentTimeMillis();
//System.out.println(Arrays.toString(data5));
System.out.println("插入排序 用时:" + (end - start));
// 6、希尔排序
start = System.currentTimeMillis();
data6 = ss.shellSort(data6);
end = System.currentTimeMillis();
//System.out.println(Arrays.toString(data6));
System.out.println("希尔排序 用时:" + (end - start));
// 7、归并排序
start = System.currentTimeMillis();
data7 = ss.mergeSort(data7, 0, data7.length-1);
end = System.currentTimeMillis();
//System.out.println(Arrays.toString(data7));
System.out.println("归并排序 用时:" + (end - start));
}
}
当10000个数据为随机数据时,运行看看:
// 随机生成10000个序列保存于数组中
for (int i = 0; i < data.length; i++) {
data[i] = (int)(Math.random()*10000);
}
运行结果:因为数据量太大(10000个),就不输出数据了,直接看结果吧
冒泡排序 用时:482
快速排序 用时:7
选择排序 用时:129
堆排序 用时:655
插入排序 用时:152
希尔排序 用时:20
归并排序 用时:9
多次测试,结果表示,当数据的分布完全随机(没有任何规律时),快速排序和归并排序的效率是最高的,而堆排序的效率最低,这也可以理解,因为堆排序本就是树结构的排序方式,排序中用到了递归,当数据量很大的时候,递归层次更深入,不断地调用自身方法,往栈中压入数据,导致效率低下。
当10000个数据为有序(升序)数据时:
// 升序生成10000个序列保存于数组中
for (int i = 0; i < data.length; i++) {
data[i] = i;
}
运行结果:
冒泡排序 用时:85
快速排序 用时:96
选择排序 用时:73
堆排序 用时:609
插入排序 用时:2
希尔排序 用时:13
归并排序 用时:9
多次测试,结果表示当数据已有顺序且为升序时,插入排序的效率是最高的,其次是归并排序,堆排序是一如既往的低啊。
当10000个数据为有序(降序)数据时:
// 降序生成10000个序列保存于数组中
for (int i = 0; i < data.length; i++) {
data[i] =data.length-i-1;
}
运行结果:
冒泡排序 用时:369
快速排序 用时:283
选择排序 用时:152
堆排序 用时:673
插入排序 用时:258
希尔排序 用时:16
归并排序 用时:7
多次测试,结果表示当数据已有顺序且为降序时,归并排序的效率是最高的,其次是希尔排序,此时的插入排序反而不是最佳选择。
总结:测试到这里,会不会想,不管数据的分布有无规律,归并排序的效率都很高,那以后不管遇到什么数据就直接使用归并排序算法好了啊,这是肯定不行的,因为本文的测试只是针对各算法的时间复杂度进行的,而讨论一个算法的优劣,除了时间复杂度之外,还应该将空间复杂度考虑进去,如冒泡,希尔,选择,堆排序,插入排序的空间复杂度为O(1),因为这些算法在程序中只需要开辟一个临时变量来保存中转值即可,但快速排序和归并排序就不同,归并排序需要开辟出和原数组一样大小的数组来保存排序好的数据,故归并排序的空间复杂度为O(n)。所以,在日常的算法设计中,需要结合处理时间以及内存占用两方面进行选择。