1. 程式人生 > >數據結構與算法——排序算法

數據結構與算法——排序算法

shells lte 交換兩個數 while ons 並排 大於 left 穩定排序

1.排序算法的分類
排序算法:基本排序,多路歸並排序
>基本排序:交換排序,選擇排序,插入排序,合並排序
>>交換排序:冒泡排序,快速排序
>>選擇排序:選擇排序,堆排序
>>插入排序:插入排序,Shell排序

2.冒泡排序算法
(1)流程:
>1.對數組中的各數據,依次比較相鄰的兩個元素的大小;
>2.如果前面的數據大於後面的,則利用中間變量交換兩個數據。經過一輪之後,便將最小的數據排好;
>3.再用同樣的方法將剩下的數據排好

、、、
viod bubbleSort(int[] a){
int temp; //中間變量
for(int i=1; i<a.length; i++){
if(a[j] > a[j+1]){ //比較相鄰數據大小
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
System.out.print("每步排序結果:");
for(int k=0; k<a.lenhth; k++){
System.out.print(a[k]+" ");
}
}
}
、、、

3.選擇排序算法
(1)流程
>1.首先從原始數據種選擇一個最小的數據,將其和第一個位置的數據交換;
>2.接著從 n-1 個數據中查找最小的數據,將其和第二個位置的數據交換;
>3.不斷重復上述過程,直到最後兩個數據交換完成。

、、、
viod selectSort(int[] a){
int temp; //中間變量
int index;

for(int i=1; i<a.length; i++){
    index = i;
    for(int j=i+1; j<a.length;j++){
        if(a[j] < a[j+1]){
            index = j;
        }
    }
    if(index != i){ //比較相鄰數據大小
        temp = a[j];
        a[j] = a[index];
        a[index] = temp;
    }
    System.out.print("每步排序結果:");
    for(int k=0; k<a.lenhth; k++){
        System.out.print(a[k]+" ");   
    }
}

}
、、、

4.插入排序算法
(1)過程
>1.首先對數組的前兩個數據進行從小到大的排序;
>2.接著講第三個數據與排好序的兩個數據比較,將第三個數據插入到合適的位置;
>3.然後將第4個數據插入到已排好的前三個數據中;
>4.不斷重復上述過程,直到排好最後一個數據。

、、、
viod insertionSort(int[] a){
int i, j, t, h;

for(i=1; i<a.length; i++){
    t=a[i];
    j=i-1;
    while(j >= 0 && t<a[j]){
        a[j+1] = a[j];
        j--;
    }
    a[j+1]=t; 
    System.out.print("每步排序結果:");
    for(int k=0; k<a.lenhth; k++){
        System.out.print(a[k]+" ");   
    }
}

}
、、、

5.Shell排序算法
(1)流程:
>1.將有n個元素的數組分成你n/2(取整)個數字序列,第1個數據和第n/2+1個數據為一對...
>2.依次循環使每一個序列對排好順序
>3.然後再變成n/4(取整)個序列,再次排序
>4.不斷重復,隨著序列的變少直到變成一個

、、、
viod shellSort(int[] a){
int i, j, h;
int r, temp;
int x=0;

for(r=a.length/2; r>=1;r/=2){
    for(i=r; i<a.length; i++){
        temp=a[i];
        j=i-r;
        while(j >= 0 && temp<a[j]){
            a[j+r]=a[j];
            j-=r;
        }
        a[j+r]=temp;
    }
    x++;
    System.out.print("第" +x+"步排序結果:");
    for(int k=0; k<a.lenhth; k++){
        System.out.print(a[k]+" ");   
    }
}

}
、、、

6.快速排序算法
(1)流程
>1.首先設定一個分界值,通過該值將數組分為左右兩個部分;
>2.將大於等於分界值的數據集中到數組右邊,小於的集中在數組左邊;
>3.然後將左邊和右邊的數據獨立快速排序;
>4.重復上述過程,直到完成,(遞歸)。

、、、
viod quickSort(int[] arr, int left, int right ){
int f, t;
int rtemp, ltemp;

ltemp=left;
rtemp=right;
f=arr[(left+right)/2];

while(ltemp<rtemp){
    while(arr[ltemp]<f){
        ++itemp;
    }
    while(arr[rtemp]>f){
        --rtemp;
    }
    if(ltemp<=rtemp){
        t=arr[ltemp];
        arr[ltemp]=arr[rtemp];
        arr[rtemp]=t;
        --rtemp;
        ++ltemp;
    }
}
if(ltemp==rtemp){
    ltemp++;
}
if(left<rtemp){
    quickSort(arr, left, ltemp-1);
}
if(ltemp<right){
    quickSort(arr, rtemp+1, right);
}

}
、、、

7.堆排序算法
堆排序的關鍵是首先構造堆結構。堆結構是一種樹結構,準確的是一個完全二叉樹,每個結點對應於原始數據的一個記錄,並且每個結點應滿足以下條件:
>如果按照從小到大的順序,要求非葉結點的數據要大於或等於其左、右子結點的數據;
>如果按照從大到小的順序,要求非葉結點的數據要小於或等於其左、右子結點的數據。

(1)流程(要求:從小到大輸出)
>1.構造堆結構:把原始的無序數據按堆結構的定義進行調整。
>>首先:將原始數據放置到一個完全二叉樹的各個結點中
>>然後:由完全二叉樹的下層想上層逐層對父子結點的數據進行比較,使父結點數據大於子結點數據,到滿足堆結構
>2.堆排序輸出:將根結點與最後葉結點互換,並輸出交換後的最後葉結點的值(即最大值)。

、、、
viod heapSort(int[] a, int n ){
int i, j, h, k;
int t;

for(i=n/2-1; i>=0; i--){
    while(2*i+1<n){
        j=2*i+1;
        if(j+1<n ){
            if(a[j])<a[j+1]{
                j++;                    
            }
        }
        if(a[i]<a[j]){
            t=a[i];
            a[i]=a[j];
            a[j]=t;
            i=j;
        }else{
            break;
        }
    }
}
//輸出構成的堆
System.out.print("原數據構成的堆:");
for(h=0; h<n; h++){
    System.out.print(a[h]+" ");
}
System.out.print("\n ");

for(i=n-1; i>0; i--){
    t=a[0];
    a[0]=a[i];
    a[i]=t;
    k=0;
    while(2*k+1<i){
        j=2*k+1;
        if(j+1<i){
            if(a[j]<a[j+1]){
                j++;
            }
        }
        if(a[k]<a[j]){
            t=a[k];
            a[k]=a[j];
            a[j]=t;
            k=j;
        }else{
            break;
        }
    }
    System.out.print("第"+(n-i)+"步排序結果:");
    for(h=0; h<n; h++){
        System.out.print(a[h]+" ");
    }
    System.out.print("\n ");
}

}
、、、

8.合並排序算法
就是將多個有序數據表合並成一個有序數據表。如果是兩個有序表的合並,則稱為二路合並。
基本思路:首先將含有 n 個結點的帶排序數據序列看成是由n個長度為1 的有序子表組成,將其依次進行兩兩合並並排序,得到長度為2的若幹個有序子表;然後再對這些子表進行兩兩合並並排序,得到長度為4的若幹個有序子表...

、、、
void mergeOne(int a[], int b[], int n, int len){
int i, j, s=0,e;
while(s+len<n){
e=s+2*len-1;
if(e>=n){ //
e=n-1;
}
//相鄰有序段合並
k=s;
i=s;
j=s+len;
while(i<s+len && j<=e){
if(a[i]<=a[j]){
b[k++]=a[i++];
}else{
b[k++]=a[j++];
}
}
while(i<s+len){
b[k++]=a[i++];
}
while(j<=e){
b[k++]=a[j++];
}
s=e+1;
}
if(s<n){
for(; s<n; s++){
b[s]=a[s];
}
}
}

void mergeSort(int a[],int n ){
int h, count=0, len=1, f=0;
int[] p=new int[n];
while(len<n){
if(f==1){
mergeOne(p, a, n,len);
}else{
mergeOne(a, p, n, len);
}
len=len*2;
f=1-f;
count++;
System.out.print("第"+count+"步排序結果");
for(h=0; h<SIZE; h++){
System.out.print(a[h]+" ");
}
System.out.print("\n");
}
if(f==1){
for(h=0; h<n; h++){
a[h]=p[h];
}
}
}
、、、

9.排序算法的效率
數據量大小 n,各種排序算法的計算復雜度:
(1)冒泡排序:平均速度O(n^2),最壞情況下速度O(n^2);
(2)快速排序:平均速度O(nlogn),最壞情況下速度O(n^2);
(3)選擇排序:平均速度O(n^2),最壞情況下速度O(n^2);
(4)堆排序:平均速度O(nlogn),最壞情況下速度O(nlogn);
(5)插入排序:平均速度O(n^2),最壞情況下速度O(n^2);
(6)Shell排序:平均速度O(n^(3/2)),最壞情況下速度O(n^2);
(7)合並排序:平均速度O(nlogn),最壞情況下速度O(nlogn).
其它概念:
穩定排序算法:依照相等的關鍵字維持記錄的相對次序來進行排序。通俗地講,對於兩個有相等關鍵字的數據D1和D2,在待排序的數據中D1出現在D2之前,在排序過後的數據中D1也在D2之前,稱為穩定排序算法。

數據結構與算法——排序算法