快速排序,冒泡排序,選擇排序是比較基礎的排序方法,我通過隨機生成一個大小1000的數組,然后使用內部類創建線程來比較耗費時間
首先快速排序算法:
快速排序算法其實也叫分治法, 其步驟大致可以分為這么幾步:
1. 先從數列中取出一個數作為基准數Num(取得好的話, 是可以減少步驟的)
2. 分區, 將大於Num的數放在它的右邊, 小於或等於它的數放在它的左邊
3. 再對左右區間重復前兩操作, 直到各個區間只有一個數為止.
這里是使用遞歸方式創建的快速排序
1 public static void kspxSort(int[] a,int low, int hight) { 2 int start=low; 3 int end=hight; 4 int key=a[low]; 5 while(end>start) { 6 //從end開始和key比較 7 while(end>start&&a[end]>=key) { 8 end--; 9 } 10 if(a[end]<=key) { 11 int temp = a[end]; 12 a[end] = a[start]; 13 a[start] = temp; 14 } 15 while(end>start&&a[start]<=key) { 16 start++; 17 18 } 19 if(a[start]>=key) { 20 int temp = a[start]; 21 a[start]=a[end]; 22 a[end]=temp; 23 } 24 25 26 } 27 28 //遞歸調用 29 if(start>low) {kspxSort(a,low,start-1);} 30 if(end<hight) {kspxSort(a,end+1,hight);} 31 32 }
然后是冒泡排序
將要排序的一組數字進行遍歷。
第一次遍歷,將相鄰的兩個數字進行比較,直到這組數字全部比較完成,如果前面比后面的數字大,則進行交換位置,此時可以將最大的數字篩選出來,放到最后的位置上。
第二次遍歷,將相鄰的兩個數字進行比較,直到這組數字全部比較完成,如果前面比后面的數字大,則進行交換位置,將這組數字里面第二大的數字篩選出來,放到倒數第二的位置上。
依次進行遍歷,交換位置,直到排序完成。
1 public static void bubbleSort(int[] a) { 2 int n = a.length; 3 int temp; 4 for(int i=0;i<n-1;i++) { 5 6 for(int j=0;j<n-1-i;j++) { 7 8 if(a[j]>a[j+1]) { 9 temp = a[j]; 10 a[j] =a[j+1]; 11 a[j+1] = temp; 12 } 13 } 14 } 15 }
然后是選擇排序
將要排序的一組數字進行遍歷。
第一次遍歷,將第一個位置上的數字與后面的數字進行比較,如果后面的數字比第一個位置上的元素小,則將兩個數字的位置進行交換。
第二次遍歷,將第二個位置上的數字與后面的數字進行比較,如果后面的數字比第二個位置上的元素小,則將兩個數字的位置進行交換。
依次進行遍歷、位置交換,直到這組數字排序完成。
1 public static void selectSort(int[] a) { 2 for(int i=0;i<a.length-1;i++){ 3 4 //假設第一個數據是最小值 5 //記錄最小值元素的下標 6 int min = i; 7 8 for(int j=i+1;j<a.length;j++){ 9 10 if(a[min]>a[j]){ 11 //給min重新賦值 12 min = j; 13 } 14 } 15 16 //交換位置 17 if(min != i){ 18 int temp; 19 temp = a[i]; 20 a[i] = a[min]; 21 a[min] = temp; 22 } 23 24 } 25 }
然后再main方法主線程中中創建一個隨機數組,大小100000;讀者可以創建更大以便獲得更好的效果;
1 int[] arry= new int[100000]; 2 for(int i=0;i<100000;i++) { 3 arry[i]= (int)(Math.random()*100000); 4 }
使用多線程調用
1 new Thread() { // 1.繼承Thread類 2 public void run() { // 2.重寫run方法 3 long t1 = new Date().getTime(); 4 kspxSort(arry, 0, arry.length-1); 5 long t2 = new Date().getTime(); 6 System.out.println("快速排序消耗時間:"+(t2-t1)); 7 } 8 }.start(); // 4.開啟線程 9 new Thread() { 10 public void run() { 11 long t1 = new Date().getTime(); 12 bubbleSort(arry); 13 long t2 = new Date().getTime(); 14 System.out.println("冒泡排序消耗時間:"+(t2-t1)); 15 } 16 }.start(); 17 new Thread() { 18 public void run() { 19 long t1 = new Date().getTime(); 20 selectSort(arry); 21 long t2 = new Date().getTime(); 22 System.out.println("選擇排序消耗時間:"+(t2-t1)); 23 } 24 25 }.start();
結果如下:
快速排序消耗時間:33
選擇排序消耗時間:2515
冒泡排序消耗時間:4227
相比較之下:快速排序最快,選擇排序和冒泡排序相差不大,
在算法中用 0()函數 表示算法的時間效率與算法所處理的數據元素個數n函數關系的最常用函數是0()函數。
定義:
一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,
T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=0(f(n)),稱0(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度
對比三種算法,具體請看https://cloud.tencent.com/developer/article/1350860
首先冒泡排序是基於比較和交換的,比如我們要對n個數字排序,冒泡排序需要n-1次遍歷,比如我們有10個數字,第一趟循環需要比較9次,第二趟循環需要比較8次,第三趟需要比較7次,以此類推,最后一趟需要1次比較。
f(10)=9+8+7+......+1 ,可以轉為一個等差數列:
f(n)=(n-1)+(n-2)+(n-3)+......+1= (n-1)*n / 2 = 0.5n^2-0.5n
當n趨於無窮大時否f(n)=n^2/2
選擇排序類似,但是最壞情況下,選則排序需要交換n-1次,冒泡排序需要交換n^2/2
快速排序
快速排序的遞推式為:T(n)=max(T(q) + T(n-q-1)) +O(n),q為切分長度,如果每次切分都剛好切分成兩半,則 q==n-q-1, T(q)==T(n-q-1) ,則簡化為 T(n)=2T(n/2)+O(n)。換一下加法項的位置,T(n)=O(n)+2T(n/2),若 快速排序每次都會以2為低做裂變分解數組,所以最終推出來的漸近復雜度:Ο(nlog2n)
如內容有問題,懇請大佬們指出,小生定虛心接受,謝謝。