Java基本排序
长度为N的数组升序排序
一,冒泡排序
public class BubbleSort { private double[] data; public BubbleSort(double[] data) { this.data = data; } public void sort(){ for(int p = data.length - 1 ; p > 0 ; p--){ for(int i = 0 ; i < p ; i++){ if(data[i] > data[i+1] ){ double tmp = data[i]; data[i] = data[i+1]; data[i+1] = tmp; } } } } public void display(){ for(int i = 0 ; i < data.length ; i++){ System.out.print(data[i]+" "); } System.out.print("\n"); } public static void main(String[] args) { double[] data = {Math.random(),Math.random(),Math.random(),Math.random()}; BubbleSort bubbleSort = new BubbleSort(data); bubbleSort.display(); bubbleSort.sort(); bubbleSort.display(); } }
0.4125010895286405 0.1682061731460387 0.5946448214944792 0.2760597727054087 0.1682061731460387 0.2760597727054087 0.4125010895286405 0.5946448214944792
比较次数:第一次比较N-1次,第二次比较N-2次,总比较次数为(N-1) + (N-2) +...+ 1 = (N-1)*N/2
交换次数:如果数组本身为降序排序,则需交换(N-1)*N/2次,如果数组本身为升序排序,则需交换0次,如果数据是随机的,大约需要交换(N-1)*N/4次
时间复杂度:(N-1)*N/2 + (N-1)*N/4,总得来说为O(N*N)
二,选择排序
public class SelectSort { private double[] data; public SelectSort(double[] data){ this.data = data; } public void sort(){ for(int i = 0 ; i < data.length ; i++){ int flag = i; for(int j = i + 1 ; j < data.length ; j++){ if( data[j] < data[flag]){ flag = j; } } double tmp = data[i]; data[i] = data[flag]; data[flag] = tmp; } } public void display(){ for(int i = 0 ; i < data.length ; i++){ System.out.print(data[i]+" "); } System.out.print("\n"); } public static void main(String[] args) { double[] data = {Math.random(),Math.random(),Math.random(),Math.random()}; SelectSort selectSort = new SelectSort(data); selectSort.display(); selectSort.sort(); selectSort.display(); } }
0.8992760265680794 0.36366208723355853 0.5105026583966352 0.27067878126430966 0.27067878126430966 0.36366208723355853 0.5105026583966352 0.8992760265680794
比较次数:第一次比较N-1次,第二次比较N-2次,总比较次数为(N-1) + (N-2) +...+ 1 = (N-1)*N/2
交换次数:如果数组本身为降序排序,则需交换N次,如果数组本身为升序排序,则需交换0次,如果数据是随机的,大约需要交换N/2次
时间复杂度:(N-1)*N/2 + N/2,总得来说为O(N*N),但是会比冒泡排序快
三,插入排序
public class InsertSort { private double[] data; public InsertSort(double[] data) { this.data = data; } public void sort(){ for(int i = 1 ; i < data.length ; i++){ double tmp = data[i]; int insertPoint = i; while(insertPoint > 0 && data[insertPoint-1] > tmp){ data[insertPoint] = data[insertPoint-1]; --insertPoint; } if(insertPoint < i){ data[insertPoint] = tmp; } } } public void display(){ for(int i = 0 ; i < data.length ; i++){ System.out.print(data[i]+" "); } System.out.print("\n"); } public static void main(String[] args) { double[] data = {Math.random(),Math.random(),Math.random(),Math.random()}; InsertSort insertSort = new InsertSort(data); insertSort.display(); insertSort.sort(); insertSort.display(); } }
0.25855304984386873 0.5035006863323077 0.8986028814892651 0.724194607320699 0.25855304984386873 0.5035006863323077 0.724194607320699 0.8986028814892651
比较次数:第一次比较1次,第二次比较2次,总比较次数为1+2+...+(N-1)= (N-1)*N/2,每一趟排序发现插入点之前,平均只有一半的数据进行了比较,所以总的比较次数为:(N-1)*N/4
交换次数:交换次数小于比较次数,并且插入排序的交换比冒泡排序和选择排序要快
时间复杂度:(N-1)*N/4 + (N-1)*N/4,总得来说为O(N*N),但是会比选择排序快
如果数组是基本有序的,即每个数据项只需移动1次或不需要移动,那么插入排序的时间复杂度将变为O(N),这无疑是非常快的
四,表排序:
主要是利用了有序链表的特性,将数组中的所有数据插入到有序链表中,它们将自动按顺序排列,然后再顺次取出链表中的所有数据,把它们放到数组中,数组便排好序了
public class SortedList { private class Data{ private double d; private Data next = null; Data(double d){ this.d = d; } } private Data first = null; public void insert(double d){ Data data = new Data(d); Data pre = null; Data cur = first; while(cur != null && (data.d > cur.d)){ pre = cur; cur = cur.next; } if(pre == null) first = data; else pre.next = data; data.next = cur; } public double deleteFirst() throws Exception{ if(first == null) throw new Exception("empty!"); Data temp = first; first = first.next; return temp.d; } }
public class ListSort { private double[] data; private SortedList sl; public ListSort(double[] data){ this.data = data; sl = new SortedList(); } public void sort() throws Exception{ for(int i = 0 ; i< data.length ; i++){ sl.insert(data[i]); } for(int i = 0 ; i< data.length ; i++){ data[i] = sl.deleteFirst(); } } public void display(){ for(int i = 0 ; i < data.length ; i++){ System.out.print(data[i]+" "); } System.out.print("\n"); } public static void main(String[] args) throws Exception{ double[] data = {Math.random(),Math.random(),Math.random(),Math.random()}; ListSort ls = new ListSort(data); ls.display(); ls.sort(); ls.display(); } }
0.6379262500544237 0.18329827548195576 0.8408253367598466 0.6213596557610592 0.18329827548195576 0.6213596557610592 0.6379262500544237 0.8408253367598466
比较次数:将数据插入链表平均需要比较N/2次
交换次数:将数组数据放入链表,再将链表数据放回数组,总共需移动2N次
时间复杂度:N/2 + 2N,总得来说为O(N)
虽然排序速度比上面3种排序方式要快,但是需要大约2倍的内存空间,数组和链表同时存在于内存中