Java中的排序
Java中的排序
排序方法的選擇
1.若n較小(如n≤50),可采用直接插入或直接選擇排序。當(dāng)記錄規(guī)模較小時,直接插入排序較好;否則因為直接選擇移動的記錄數(shù)少于直接插入,應(yīng)選直接選擇排序為宜。
2.若文件初始狀態(tài)基本有序(指正序),則應(yīng)選用直接插入、冒泡或隨機(jī)的快速排序為宜;
3.若n較大,則應(yīng)采用時間復(fù)雜度為O(nlgn)的排序方法:快速排序、堆排序或歸并排序。
衡量排序算法的優(yōu)劣:
1.時間復(fù)雜度:分析關(guān)鍵字的比較次數(shù)和記錄的移動次數(shù)
2.空間復(fù)雜度:分析排序算法中需要多少輔助內(nèi)存
3.穩(wěn)定性:若兩個記錄A和B的關(guān)鍵字值相等,但排序后A、B的先后次序保持不變,則稱這種排序算法是穩(wěn)定的。
排序算法分類:內(nèi)部排序和外部排序。
1.內(nèi)部排序:整個排序過程不需要借助于外部存儲器(如磁盤等),所有排序操作都在內(nèi)存中完成。
2.外部排序:參與排序的數(shù)據(jù)非常多,數(shù)據(jù)量非常大,計算機(jī)無法把整個排序過程放在內(nèi)存中完成,必須借助于外部存儲器(如磁盤)。外部排序最常見的是多路歸并排序。可以認(rèn)為外部排序是由多次內(nèi)部排序組成。
常用的內(nèi)部排序
選擇排序
基本原理:將待排序的元素分為已排序(初始為空)和未排序兩組,依次將未排序的元素中值最小的元素放入已排序的組中。直接選擇排序簡單直觀,但性能略差;堆排序是一種較為高效的選擇排序方法,但實現(xiàn)起來略微復(fù)雜。
基本過程:1.在一組元素R[i]到R[n]中選擇具有最小關(guān)鍵字的元素。2.若它與這組元素中的第一個元素,則將它與這組元素中的第一個元素對調(diào)。3.去除具有最小關(guān)鍵字的元素,在剩下的元素中重復(fù)1、2步,直到剩余元素只有一個為止。
算法的時間效率:無論初始狀態(tài)如何,在第i趟排序中選擇最小關(guān)鍵碼的元素,需做n-i次比較,因此總的比較次數(shù)為:n(n-1)/2 = O(n^2)
算法的空間效率:空間效率很高,只需要一個附加程序單元用于交換,其空間效率為:O(1)
算法的穩(wěn)定性:不穩(wěn)定
public class SelectSort {public static void selectSort(DataWrap[] data) {System.out.println("開始排序");int arrayLength = data.length;for (int i = 0; i < arrayLength - 1; i++) {for (int j = i + 1; j < arrayLength; j++) {if (data[i].compareTo(data[j]) > 0) {DataWrap temp = data[i];data[i] = data[j];data[j] = temp;}}System.out.println(java.util.Arrays.toString(data));}}public static void main(String[] args) {DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),new DataWrap(21, "*"), new DataWrap(23, ""),new DataWrap(-30, ""), new DataWrap(-49, ""),new DataWrap(21, ""), new DataWrap(30, "*"),new DataWrap(30, "") };System.out.println("排序之前:\n" + java.util.Arrays.toString(data));selectSort(data);System.out.println("排序之后:\n" + java.util.Arrays.toString(data));} }堆排序
算法的時間效率:假設(shè)有n個數(shù)據(jù),需要進(jìn)行n-1次建堆,每次建堆本身耗時 logn,則其時間效率為O(nlogn)
算法的空間效率:空間效率很高,只需要一個附加程序單元用于交換,其空間效率為O(1)
算法的穩(wěn)定性:不穩(wěn)定
public class HeapSort {public static void heapSort(DataWrap[] data) {System.out.println("開始排序");int arrayLength = data.length;// 循環(huán)建堆for (int i = 0; i < arrayLength - 1; i++) {// 建堆builMaxdHeap(data, arrayLength - 1 - i);// 交換堆頂和最后一個元素swap(data, 0, arrayLength - 1 - i);System.out.println(java.util.Arrays.toString(data));}}// 對data數(shù)組從0到lastIndex建大頂堆private static void builMaxdHeap(DataWrap[] data, int lastIndex) {// 從lastIndex處節(jié)點(最后一個節(jié)點)的父節(jié)點開始for (int i = (lastIndex - 1) / 2; i >= 0; i--) {// k保存當(dāng)前正在判斷的節(jié)點int k = i;// 如果當(dāng)前k節(jié)點的子節(jié)點存在while (k * 2 + 1 <= lastIndex) {// k節(jié)點的左子節(jié)點的索引int biggerIndex = 2 * k + 1;// 如果biggerIndex小于lastIndex,即biggerIndex +1// 代表k節(jié)點的右子節(jié)點存在if (biggerIndex < lastIndex) {// 如果右子節(jié)點的值較大if (data[biggerIndex].compareTo(data[biggerIndex + 1]) < 0) {// biggerIndex總是記錄較大子節(jié)點的索引biggerIndex++;}}// 如果k節(jié)點的值小于其較大子節(jié)點的值if (data[k].compareTo(data[biggerIndex]) < 0) {// 交換它們swap(data, k, biggerIndex);// 將biggerIndex賦給k,開始while循環(huán)的下一次循環(huán)// 重新保證k節(jié)點的值大于其左、右節(jié)點的值k = biggerIndex;} else {break;}}}}// 交換data數(shù)組中i、j兩個索引處的元素private static void swap(DataWrap[] data, int i, int j) {DataWrap temp = data[i];data[i] = data[j];data[j] = temp;}public static void main(String[] args) {DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),new DataWrap(21, "*"), new DataWrap(23, ""),new DataWrap(-30, ""), new DataWrap(-49, ""),new DataWrap(21, ""), new DataWrap(30, "*"),new DataWrap(30, "")};System.out.println("排序之前:\n" + java.util.Arrays.toString(data));heapSort(data);System.out.println("排序之后:\n" + java.util.Arrays.toString(data));} }冒泡排序
相鄰兩元素進(jìn)行比較,如有需要則進(jìn)行交換,每完成一次循環(huán)就將最大元素排在最后(如從小到大排序),下一次循環(huán)是將其它的數(shù)進(jìn)行類似操作。
算法的時間效率:從冒泡排序的算法可以看出,若待排序的元素為正序,則只需進(jìn)行一趟排序,比較次數(shù)為n-1次,移動元素次數(shù)為0;若待排序的元素為逆序,則需要進(jìn)行n-1趟排序,比較次數(shù)為(n^2-n)/2 ,移動次數(shù)為3(n^2-n)/2,因此時間復(fù)雜度為O(n^2)
算法的空間效率:空間效率很高,只需要一個附加程序單元用于交換,其空間效率為O(1)
算法的穩(wěn)定性:穩(wěn)定
public class BubbleSort {public static void bubbleSort(DataWrap[] data) {System.out.println("開始排序");int arrayLength = data.length;for (int i = 0; i < arrayLength - 1; i++) {boolean flag = false;for (int j = 0; j < arrayLength - 1 - i; j++) {if (data[j].compareTo(data[j + 1]) > 0) {DataWrap temp = data[j + 1];data[j + 1] = data[j];data[j] = temp;flag = true;}}System.out.println(java.util.Arrays.toString(data));if (!flag)break;}}public static void main(String[] args) {DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),new DataWrap(21, "*"), new DataWrap(23, ""),new DataWrap(-30, ""), new DataWrap(-49, ""),new DataWrap(21, ""), new DataWrap(30, "*"),new DataWrap(30, "")};System.out.println("排序之前:\n" + java.util.Arrays.toString(data));bubbleSort(data);System.out.println("排序之后:\n" + java.util.Arrays.toString(data));} }快速排序
算法的時間效率:時間效率很好,因為每趟能確定的元素都呈指數(shù)增長,故時間復(fù)雜度為log(n+1)
算法的空間效率:由于使用遞歸,而遞歸使用棧,因此空間效率最優(yōu)時為log(n)
算法的穩(wěn)定性:由于包含跳躍式交換,因此不穩(wěn)定
public class QuickSort {private static void swap(DataWrap[] data, int i, int j) {DataWrap temp = data[i];data[i] = data[j];data[j] = temp;}private static void subSort(DataWrap[] data, int start, int end) {if (start < end) {DataWrap base = data[start];int i = start;int j = end + 1;while (true) {while (i < end && data[++i].compareTo(base) <= 0);while (j > start && data[--j].compareTo(base) >= 0);if (i < j) {swap(data, i, j);} else {break;}}swap(data, start, j);subSort(data, start, j - 1);subSort(data, j + 1, end);}}public static void quickSort(DataWrap[] data){subSort(data,0,data.length-1);}public static void main(String[] args) {DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),new DataWrap(21, "*"), new DataWrap(23, ""),new DataWrap(-30, ""), new DataWrap(-49, ""),new DataWrap(21, ""), new DataWrap(30, "*"),new DataWrap(30, "") };System.out.println("排序之前:\n" + java.util.Arrays.toString(data));quickSort(data);System.out.println("排序之后:\n" + java.util.Arrays.toString(data));} }總結(jié)
- 上一篇: action中写php函数,WordPr
- 下一篇: Java 试题一