1. 程式人生 > >淺談排序演算法的效率(二)—(Java筆記)

淺談排序演算法的效率(二)—(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 = data.length - 1; 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;
	}

	public static void main(String[] args) {
		// 各排序演算法效率比較
		long start;// 記錄演算法開始的時間
		long end;// 記錄演算法結束的時間
		SortSummary ss = new SortSummary();
		int[] data = new int[10000];
		// 隨機生成10000個序列保存於陣列中
		for (int i = 0; i < data.length; i++) {
			data[i] = (int) (Math.random() * 10000);
		}
		int[] data1=new int[10000];
		int[] data2=new int[10000];
		int[] data3=new int[10000];
		int[] data4=new int[10000];
		int[] data5=new int[10000];
		int[] data6=new int[10000];
		//複製陣列,java中對陣列的複製只能是System.arraycopy
		System.arraycopy(data, 0, data1, 0, data.length);
		System.arraycopy(data, 0, data2, 0, data.length);
		System.arraycopy(data, 0, data3, 0, data.length);
		System.arraycopy(data, 0, data4, 0, data.length);
		System.arraycopy(data, 0, data5, 0, data.length);
		System.arraycopy(data, 0, data6, 0, data.length);
		
		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));
	}

}

當10000個數據為隨機資料時,執行看看:

// 隨機生成10000個序列保存於陣列中
		for (int i = 0; i < data.length; i++) {
			data[i] = (int)(Math.random()*10000);
		}
執行結果:因為資料量太大(10000個),就不輸出資料了,直接看結果吧
氣泡排序  用時:484
快速排序  用時:8
選擇排序  用時:109
堆排序  用時:572
插入排序  用時:142
希爾排序  用時:20

多次測試,結果表示,當資料的分佈完全隨機(沒有任何規律時),快速排序的效率是最高的,而堆排序的效率最低,這也可以理解,因為堆排序本就是樹結構的排序方式,排序中用到了遞迴,當資料量很大的時候,遞迴層次更深入,不斷地呼叫自身方法,往棧中壓入資料,導致效率低下。

當10000個數據為有序(升序)資料時:

// 升序生成10000個序列保存於陣列中
		for (int i = 0; i < data.length; i++) {
			data[i] = i;
		}
執行結果:
氣泡排序  用時:82
快速排序  用時:97
選擇排序  用時:75
堆排序  用時:642
插入排序  用時:2
希爾排序  用時:15

多次測試,結果表示當資料已有順序且為升序時,插入排序的效率是最高的,堆排序是一如既往的低啊。

當10000個數據為有序(降序)資料時:

// 降序生成10000個序列保存於陣列中
		for (int i = 0; i < data.length; i++) {
			data[i] =data.length-i-1;
		}
執行結果:
氣泡排序  用時:373
快速排序  用時:287
選擇排序  用時:150
堆排序  用時:682
插入排序  用時:265
希爾排序  用時:18

多次測試,結果表示當資料已有順序且為降序時,希爾排序的效率是最高的,此時的插入排序反而不是最佳選擇。