浅谈排序算法的效率(二)—(Java随笔)

首先:咱也借用一下网上的那张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)。所以,在日常的算法设计中,需要结合处理时间以及内存占用两方面进行选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值