1. 程式人生 > >排序總結(C語言)

排序總結(C語言)

排序是很基礎的東西了,本篇文章總結了一下常用的排序方法,選擇排序,插入排序,氣泡排序,歸併排序,快速排序。

前面三種排序演算法效率都比較低,時間複雜度都是O(n²)

選擇排序法: 選擇排序是從N個待排序的數中找到最小的數,放到第0個位置上,然後再從剩下的N-1個數裡找到最小的,放到第1個位置上……,直到所有元素排好序。

void selectionsort(int a[],int size) //選擇排序法
{
    int i,j,min,swap;
    for(i=0;i<size-1;i++){
            min=i;
    for(j=i+1;j<size;j++){
        if(a[j]<a[min]){
            min=j;
        }
    swap=a[i];
            a[i]=a[min];
            a[min]=swap;
    }}
    for(int i=0;i<size;i++){
           cout<<a[i];
           cout<<" ";
    }

}

插入排序法

  • 插入排序法是將待排序的陣列分為有序和無序兩部分,前者在左邊,後者在右邊。
  • 開始時有序陣列只有a[0]一個元素,其餘都屬於無序部分
  • 每次取出無序部分的第一個元素,插入到有序部分,假設插入到合適的位置p,則原p位置及其後面的有序部分元素都要依次向右移動一個位子,有序部分即增加了一個元素。
  • 直到無序部分沒有元素
void insertationsort(int a[],int size) //插入排序
{
    int i,j,temp;
    for(i=1;i<size;i++){//i為無序陣列的第一個元素
            for(j=0;j<i;j++){
                    //找到a[i]的合適位置
                if(a[j]>a[i]){
                        temp=a[i];
            //a[i]及後面有序部分元素依次右移
                    for(int k=i;k>j;k--){
                        a[k]=a[k-1];
                    }
                    a[j]=temp;
                    break;
                }
            }
    }
    for(int i=0;i<size;i++){
       cout<<a[i];
       cout<<" ";
    }
}

氣泡排序法

  • 氣泡排序法也是將待排序的演算法分為有序和無序的兩部分,前者在右,後者在左。
  • 剛開始整個陣列都是無序部分,有序部分沒有元素。
  • 每次要使得無序部分最大的元素移動到有序部分第一個元素的左邊。移動的方法是:依次比較相鄰的兩個元素,如果前面的比後面的大,就交換他們的位置。這樣,大的元素就像水裡的氣泡一樣不斷往上浮。移動結束,有序部分就增加了一個元素。
  • 直到無序部分沒有元素。 下面是程式碼實現
void bubblesort(int a[],int size)
    {
        for(int i=0;i<size-1;i++)
        for(int j=0;j<size-i;j++){
            if(a[j]>a[j+1]){
                int tmp=a[j];
                a[j]=a[j+1];
                a[j+1]=tmp;
            }
        }
        for(int i=0;i<size;i++){
            cout<<a[i]<<" ";
        }
    }

下面兩種排序法的時間複雜度均為O(nlogn)

歸併排序

  • 把前一部分排序
  • 把後一部分排序
  • 把兩半歸併到一個新的有序數組裡,然後再拷貝回原陣列
void Merge(int a[],int s,int m,int e,int tmp[])
{//a[]是待排序陣列,tmp[]是臨時存放的空陣列
    //s是待排序部分陣列起始下標,m是中間下標,e是結束下標
    int pb=0;
    int p1=s,p2=m+1;
    //將s到m,m+1到s兩部分按大小順序歸併到tmp數組裡
    while(p1<=m&&p2<=e){
        if(a[p1]<a[p2])
            tmp[pb++]=a[p1++];
            else
                tmp[pb++]=a[p2++];
    }
    //兩部分剩下的部分依次存到tmp數組裡
    while(p1<=m)
        tmp[pb++]=a[p1++];
    while(p2<=e)
        tmp[pb++]=a[p2++];
    for(int i=0;i<e-s+1;i++){
        a[s+i]=tmp[i];
    }
}
void Mergesort(int a[],int s,int e,int tmp[])
{
    if(s<e){
    int m=s+(e-s)/2;
    Mergesort(a,s,m,tmp);
    Mergesort(a,m+1,e,tmp);
    Merge(a,s,m,e,tmp);
    }
}

快速排序

  • 設k=a[0],將k挪到適當位置,使得比k小的元素都在k左邊,比k大的元素都在k右邊,和k相等的,不關心在k左右出現均可。
  • 把k左邊的部分快速排序
  • 把k右邊的部分快速排序
void swap(int &a,int &b)
{
    int tmp=a;
    a=b;
    b=tmp;
}
void Quicksort(int a[],int s,int e)
{//a[]為待排序陣列,s為待排序部分起始下標,e為結束下標
    if(s>=e)
        return;
    int k=a[s];
    int i=s,j=e;
    while(i!=j){
        while(a[j]>=k&&i<j)
            j--;
        swap(a[i],a[j]);
        while(a[i]<=k&&i<j)
            i++;
        swap(a[i],a[j]);
    }
    Quicksort(a,s,i-1);
    Quicksort(a,i+1,e);
}