由於最近要找實習單位便在刷算法題,發現許多算法題都涉及到排序的知識所以今天把排序的內容總結一遍備忘。博客中的內容大部分是參考《王道數據結構》
內部排序分爲幾類分別爲:插入排序(直接插入排序、希爾排序),交換排序(冒泡排序、快速排序),選擇排序(簡單選擇排序、堆排序),歸併排序和基數排序。
各大排序的比較如下圖所示:
一、插入排序
1.1直接插入排序
package sort;
public class insertSort {
public insertSort(int[] a){
int temp = 0;
for(int i=1;i<a.length;i++){
int j=i-1; //j表示已排序好的最後一個數
temp = a[i]; //temp表示待插入的數字
for(;j>=0&&a[j]>temp;j--){
a[j+1]=a[j];
}
a[j+1] = temp; //此時的j+1表示爲待插入數字的位置
}
}
private void print(int[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
}
public static void main(String[] args){
int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35};
insertSort sort = new insertSort(a);
sort.print(a);
}
}
1.2折半插入排序
package sort;
public class insertSort2 {
public insertSort2(int[] a){
int temp=0,low,high,mid;
for(int i=1;i<a.length;i++){
int j = i-1;
temp=a[i];
low=0;
high=i-1;
while(low<=high){ //使用折半查找待插入數據的位置
mid = (low+high)/2;
if(a[i]>a[mid]) low=mid+1;
else high=mid-1;
}
for(j=i-1;j>=high+1;j--){
a[j+1]=a[j];
}
a[j+1]=temp;
}
}
private void print(int[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+",");
}
}
public static void main(String[] args){
int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15};
insertSort2 sort = new insertSort2(a);
sort.print(a);
}
}
從上述算法中不難看出折半插入排序僅僅是減少了比較元素的次數而比較次數與待排序的初始狀態無關,僅取決於表中的元素的個數,故折半插入排序的時間複雜度仍爲O(n^2)。1.3希爾排序(縮小增量排序)
package sort;
public class shellSort {
public shellSort(int[] a){
double d = a.length;
while(true){
d = Math.ceil(d/2.0);
int dm = (int)d;
int temp = 0;
for(int n=0;n<dm;n++){ //對整體進行增量爲dm的插入排序
for(int i=n+dm;i<a.length;i+=dm){ //進行一次插入排序
int j=i-dm;
temp = a[i];
for(;j>=0&&a[j]>temp;j-=dm){
a[j+dm] = a[j];
}
a[j+dm] = temp;
}
}
if(dm==1) return ; //進行了增量爲1的排序後跳出循環
}
}
private void print(int[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+",");
}
}
public static void main(String[] args){
int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35};
shellSort sort = new shellSort(a);
sort.print(a);
}
}