前言本文講解常見排序算法的分析與實現(xiàn),具體包括冒泡排序;選擇排序;插入排序;希爾排序;歸并排序;快速排序;算法實現(xiàn)采用Java和C 兩種語言。 一、冒泡排序(時間復(fù)雜度O(N^2))
/*冒泡排序:時間復(fù)雜度為n^2*/ public class Bubble { public static void sort(Comparable[] a) { for (int i=a.length-1;i>0;i--) //多少個元素進行排序 { for (int j=0;j<i;j ) //多少個元素進行比較 { if(greater(a[j],a[j 1])) //執(zhí)行次數(shù): (n-1) (n-2) ... 1=((n-1) 1)*(n-1)/2=n^2/2 - n/2 exch(a,j,j 1); // 最壞情況下執(zhí)行次數(shù):(n-1) (n-2) ... 1=((n-1) 1)*(n-1)/2=n^2/2 - n/2 // 因此時間復(fù)雜度為 n^2 -n 即O(n^2) } } } private static boolean greater(Comparable v,Comparable w) { return v.compareTo(w)>0; } private static void exch(Comparable[] a,int i,int j) { Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
/* Bubble sort */ #include<iostream> using namespace std; //compare the size greater of A and B template<typename T> bool bigger(T a,T b); //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j); //printf arrar template<typename T> void prt(T data[],int N); template<typename T> void bubble(T data[],int N); int main() { int a[]={1,2,3,8,7,6}; prt(a,6); bubble(a,6); prt(a,6); return 1; } template<typename T> void bubble(T data[],int N) { for(int i=N-1;i>0;i--) { for(int j=0;j<i;j ) { if(bigger(data[j],data[j 1])) exch(data,j,j 1); } } } //printf arrar template<typename T> void prt(T data[],int N) { for(int i=0;i<N;i ) cout<<data[i]<<" "; cout<<endl; } //compare the size greater of A and B template<typename T> bool bigger(T a,T b) { return a>b; } //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j) { T temp=data[i]; data[i]=data[j]; data[j]=temp; } 二、選擇排序(時間復(fù)雜度O(N^2))
/*選擇排序, 時間復(fù)雜度:O(n^2)*/ public class Selection { public static void Sort(Comparable[] a) { for (int i=0;i<=a.length-2;i ) //待選擇元素 { int minIndex=i; for (int j=i 1;j<a.length;j ) //待比較元素 { if(greater(a[minIndex],a[j])) minIndex=j; } exch(a,i,minIndex); } } private static boolean greater(Comparable a, Comparable b) { return a.compareTo(b)>0; } private static void exch(Comparable[] a,int i,int j) { Comparable temp=a[i]; a[i]=a[j]; a[j]=temp; } }
/* Selection sort */ #include<iostream> using namespace std; //compare the size greater of A and B template<typename T> bool bigger(T a,T b); //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j); //printf arrar template<typename T> void prt(T data[],int N); template<typename T> void selection(T data[],int N); int main() { int a[]={8,7,6,3,2,1}; prt(a,6); selection(a,6); prt(a,6); return 1; } template<typename T> void selection(T data[],int N) { for(int i=0;i<N-1;i ) { int minIndex=i; for(int j=i;j<N;j ) { if(bigger(data[minIndex],data[j])) { minIndex=j; } } exch(data,i,minIndex); } } //printf arrar template<typename T> void prt(T data[],int N) { for(int i=0;i<N;i ) cout<<data[i]<<" "; cout<<endl; } //compare the size greater of A and B template<typename T> bool bigger(T a,T b) { return a>b; } //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j) { T temp=data[i]; data[i]=data[j]; data[j]=temp; }
三、插入排序(時間復(fù)雜度O(N^2))
/*插入排序;時間復(fù)雜度為:O(N^2) */ public class Insertion { public static void sort(Comparable[] a) { for (int i=1;i<a.length;i ) //未排序的元素 { for (int j=i;j>0;j--) //已排序的元素 { if(greater(a[j-1],a[j])) //最壞情況的比較次數(shù):n^2/2 - n/2 exch(a,j-1,j); //最壞情況的交換次數(shù):n^2/2 - n/2 else break; } } } private static boolean greater(Comparable v,Comparable w) { return v.compareTo(w)>0; } private static void exch(Comparable[] a,int i,int j) { Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
/* Bubble sort */ #include<iostream> using namespace std; //compare the size greater of A and B template<typename T> bool bigger(T a,T b); //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j); //printf arrar template<typename T> void prt(T data[],int N); template<typename T> void insertion(T data[],int N); int main() { int a[]={8,7,6,3,2,1}; prt(a,6); insertion(a,6); prt(a,6); return 1; } template<typename T> void insertion(T data[],int N) { for(int i=1;i<N;i ) { for(int j=i;j>0;j--) { if(bigger(data[j-1],data[j])) exch(data,j,j-1); } } } //printf arrar template<typename T> void prt(T data[],int N) { for(int i=0;i<N;i ) cout<<data[i]<<" "; cout<<endl; } //compare the size greater of A and B template<typename T> bool bigger(T a,T b) { return a>b; } //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j) { T temp=data[i]; data[i]=data[j]; data[j]=temp; } 四、希爾排序希爾排序是插入排序的一種,又稱“縮小增量排序”,是插入排序算法的一種更高效的改進版本。
h=1; while(h<N/2) h=2h 1;
h=h/2;
public class Shell { public static void sort(Comparable[] a) { int h=1; while (h<a.length/2) { h=2*h 1; //確定增長量h的初值 } // 分而治之,先讓數(shù)據(jù)局部有需序(各個大組有序,大組逐漸變小組),再進行最終的全部有序 while (h>=1) { for (int i=h;i<a.length;i ) { for (int j=i;j>=h;j-=h) { if(greater(a[j-h],a[j])) exch(a,j-h,j); else break; } } h=h/2; //減小h的值 } } private static boolean greater(Comparable a, Comparable b) { return a.compareTo(b)>0; } private static void exch(Comparable[] a,int i,int j) { Comparable temp=a[i]; a[i]=a[j]; a[j]=temp; } }
/* Bubble sort */ #include<iostream> using namespace std; //compare the size greater of A and B template<typename T> bool bigger(T a,T b); //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j); //printf arrar template<typename T> void prt(T data[],int N); template<typename T> void shell(T data[],int N); int main() { int a[]={8,7,6,3,2,1}; prt(a,6); shell(a,6); prt(a,6); return 1; } template<typename T> void shell(T data[],int N) { int h=1; while(h<N/2) //initial h value h=2*h 1; while(h>=1) { for(int i=h;i<N;i ) { for(int j=i;j>=h;j-=h) { if(bigger(data[j-h],data[j])) exch(data,j,j-h); else break; } } h/=2; //decrease h value } } //printf arrar template<typename T> void prt(T data[],int N) { for(int i=0;i<N;i ) cout<<data[i]<<" "; cout<<endl; } //compare the size greater of A and B template<typename T> bool bigger(T a,T b) { return a>b; } //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j) { T temp=data[i]; data[i]=data[j]; data[j]=temp; } 五、歸并排序(時間復(fù)雜度O(nlogn))
/*歸并排序 ,典型的分而治之的策略,先把所有的元素分開,然后再一一攻破;時間復(fù)雜度為O(nlogn)*/ public class Merge { private static Comparable[] assist;//完成歸并操作需要的輔助數(shù)組 //對數(shù)組內(nèi)的元素進行排序 public static void sort(Comparable[] a) { assist=new Comparable[a.length]; int minIndex=0; // 數(shù)組中最小的索引 int maxIndex=a.length-1; // 數(shù)組中最大的索引 sort(a,minIndex,maxIndex); //對數(shù)組中部分元素進行排序 } //對數(shù)組a中從索引lo到索引hi之間的元素進行排序 private static void sort(Comparable[] a, int minIndex, int maxIndex) { if(maxIndex<=minIndex) return; //將minIndex 到 maxIndex的數(shù)據(jù)分為兩組 int midIndex = minIndex (maxIndex-minIndex)/2; //分別對兩組數(shù)據(jù)進行排序 sort(a,minIndex,midIndex); sort(a,midIndex 1,maxIndex); //對兩組數(shù)據(jù)進行歸并 merge(a,minIndex,midIndex,maxIndex); } //從索引lo到所以mid為一個子組,從索引mid 1到索引hi為另一個子組,把數(shù)組a中的這兩個子組的數(shù)據(jù)合并成一個有序的大組(從索引lo到索引hi) private static void merge(Comparable[] a, int minIndex, int midIndex, int maxIndex) { //定義三個索引 int leftIndex=minIndex; // 兩組中左邊一組待比較值的位置索引 int rightIndex=midIndex 1; // 兩組中右邊一組待比較值的位置索引 int assistIndex=minIndex; // 輔助數(shù)組中待插入元素的位置索引 // 一一對應(yīng)比較兩組中的數(shù)據(jù),將較小的數(shù)據(jù)放到輔助數(shù)組中,直至有一個組的數(shù)據(jù)遍歷完 while (leftIndex<=midIndex && rightIndex <= maxIndex) { if(less(a[leftIndex],a[rightIndex])) assist[assistIndex ]=a[leftIndex ]; else assist[assistIndex ]=a[rightIndex ]; } // 將剩余一個組中的數(shù)據(jù),依次放到輔助數(shù)組中 while (leftIndex<=midIndex) assist[assistIndex ]=a[leftIndex ]; while (rightIndex<=maxIndex) assist[assistIndex ]=a[rightIndex ]; // 將輔助數(shù)組中已經(jīng)排序好的數(shù)據(jù)移動到原始數(shù)組中 for (int i=minIndex;i<=maxIndex;i ) { a[i]=assist[i]; } } //判斷v是否小于w private static boolean less(Comparable v,Comparable w) { return v.compareTo(w)<0; } //交換a數(shù)組中,索引i和索引j處的值 private static void exch(Comparable[] a,int i,int j) { Comparable temp=a[i]; a[i]=a[j]; a[j]=temp; }
/* Bubble sort */ #include<iostream> using namespace std; //compare the size greater of A and B template<typename T> bool bigger(T a,T b); //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j); //printf arrar template<typename T> void prt(T data[],int N); //data group sort template<typename T> void sort(T data[],int N); //data subgroup sort template<typename T> void sort(T data[],int minIndex,int maxIndex); //subgroup merge template<typename T> void merge(T data[],int minIndex,int midIndex,int maxIndex); //assit array int assit[6]; int main() { int a[]={8,7,6,3,2,1}; prt(a,6); sort(a,6); prt(a,6); return 1; } //data group sort template<typename T> void sort(T data[],int N) { int minIndex=0; int maxIndex=N-1; sort(data,minIndex,maxIndex); } //data subgroup sort template<typename T> void sort(T data[],int minIndex,int maxIndex) { if(minIndex>=maxIndex) return; int midIndex=minIndex (maxIndex-minIndex)/2; sort(data,minIndex,midIndex); sort(data,midIndex 1,maxIndex); merge(data,minIndex,midIndex,maxIndex); } //subgroup merge template<typename T> void merge(T data[],int minIndex,int midIndex,int maxIndex) { int leftIndex=minIndex; int rightIndex=midIndex 1; int assitIndex=minIndex; while(leftIndex<=midIndex && rightIndex<=maxIndex) { if(bigger(data[leftIndex],data[rightIndex])) assit[assitIndex ]=data[rightIndex ]; else assit[assitIndex ]=data[leftIndex ]; } while(leftIndex<=midIndex) { assit[assitIndex ]=data[leftIndex ]; } while(rightIndex<=maxIndex) { assit[assitIndex ]=data[rightIndex ]; } for(int i=minIndex;i<=maxIndex;i ) data[i]=assit[i]; } //printf arrar template<typename T> void prt(T data[],int N) { for(int i=0;i<N;i ) cout<<data[i]<<" "; cout<<endl; } //compare the size greater of A and B template<typename T> bool bigger(T a,T b) { return a>b; } //exchage element i data[i] and data[j] template<typename T> void exch(T data[],int i,int j) { T temp=data[i]; data[i]=data[j]; data[j]=temp; }
六、快速排序(時間復(fù)雜度O(nlogn))快速排序是對冒泡排序的一種改進。它的基本思想是:通過一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨立的兩部分,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小,然后再按此方法對這兩部分數(shù)據(jù)分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數(shù)據(jù)變成有序序列。
/* 快速排序 最優(yōu)情況下的時間復(fù)雜度是O(nlogn);最壞情況下的時間復(fù)雜度是O(n^2);平均情況下的時間復(fù)雜度通過歸納法推導(dǎo)可得為O(nlogn)*/ public class Quick { //對數(shù)組內(nèi)的元素進行排序 public static void sort(Comparable[] a) { int minIndex=0; int maxIndex=a.length-1; sort(a,minIndex,maxIndex); } //對數(shù)組a中從索引lo到索引hi之間的元素進行排序 private static void sort(Comparable[] a, int minIndex, int maxIndex) { if(maxIndex<=minIndex) return; // 將數(shù)據(jù)中minIndex索引到maxIndex索引之間的元素進行分組(左子組,右子組) int separatedValues = partition(a, minIndex, maxIndex); //將左子組有序 sort(a,minIndex,separatedValues-1); //將右子組有序 sort(a,separatedValues 1,maxIndex); } //對數(shù)組a中,從索引 minIndex到索引 maxIndex之間的元素進行分組,并返回分組界限對應(yīng)的索引,保證左子組的元素小于分組界限值,右子組的元素大于分組界限值 public static int partition(Comparable[] a,int minIndex,int maxIndex) { //確定分組界限值 Comparable key=a[minIndex]; //定義兩個索引值,分別指向待切分元素的最小索引處和最大索引處 int left = minIndex; int right = maxIndex 1; //切分 while (true) { //先從右往左掃描,移動right索引,直至找到一個比分界值小的元素,停止 while (less(key,a[--right])) { if(right==minIndex) break; } //再從左往右掃描,移動left索引,直至找到一個比分界值大的元素,停止 while (less(a[ left],key)) { if (left==maxIndex) break; } //判斷l(xiāng)eft是否等于right,如果是,則證明元素掃描完畢,結(jié)束循環(huán),否則,交換元素 if(left>=right) break; else exch(a,right,left); } //交換分界值 exch(a,minIndex,right); return right; //返回分界值索引 } //判斷v是否小于w private static boolean less(Comparable v,Comparable w) { return v.compareTo(w)<0; } //交換a數(shù)組中,索引i和索引j處的值 private static void exch(Comparable[] a,int i,int j) { Comparable temp=a[i]; a[i]=a[j]; a[j]=temp; } }
待更新
常見排序算法的穩(wěn)定性
|
|