1. 程式人生 > >6種排序模板

6種排序模板

看幾個動畫演示  http://atool.org/sort.php     http://jsdo.it/norahiko/oxIy/fullscreen

 

一:氣泡排序  O(n*n)

氣泡排序是一種簡單的排序演算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
int main()
{
    int a[1000],i,j,n,t;
    cin>>n;
    for(i=0;i<n;i++)
       cin>>a[i];
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-i-1;j++)
        {
            if(a[j]>=a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
        }
    }
    for(i=0;i<n;i++)
        cout<<a[i]<<" ";
    return 0;
}

二:選擇排序 O(n*n)

選擇排序(Selection-sort)是一種簡單直觀的排序演算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
int main()
{
    int a[1000],i,j,n,t,p;
    cin>>n;
    for(i=0;i<n;i++)
       cin>>a[i];
    for(i=0;i<n-1;i++)
    {
        p=i;
        for(j=i+1;j<n;j++)
        {
            if(a[p]>=a[j])
            {
                p=j;
            }
        }
        t=a[i];
        a[i]=a[p];
        a[p]=t;
    }
    for(i=0;i<n;i++)
        cout<<a[i]<<" ";
    return 0;
}

三:插入排序   O(nlogn)

n插入排序(Insertion-Sort)的演算法描述是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
ll a[10100];
int main()
{
    ll n,i,j,c,p;
    cin>>n;
    for(i=0;i<n;i++)
        cin>>a[i];
    for(i=1;i<n;i++)
    {
        p=i-1;
        c=a[i];
        while(p>=0&&a[p]>c)
        {
            a[p+1]=a[p];
            p--;
        }
        a[p+1]=c;
    }
    for(i=0;i<n;i++)
        cout<<a[i]<<" ";
    return 0;
}

四:歸併排序  O(nlogn)

合併操作(merge),是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為2-路歸併。

看個例題純模板

對每一組輸入,輸出該序列變成有序所需要交換的最少的次數。

Sample Input

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
ll a[500001],b[500001];
ll cnt;
void merge_bing(ll frist,ll mid,ll last)
{
    ll midd=mid+1;
    ll d=0;
    ll f=frist;
    while(frist<=mid&&midd<=last)
    {
        if (a[frist]<=a[midd])
            b[d++]=a[frist++];
        else
        {
            cnt+=mid-frist+1;
            b[d++]=a[midd++];
        }
    }
    while(frist<=mid)
        b[d++]=a[frist++];
    while(midd<=last)
        b[d++]=a[midd++];
    for(ll i=0;i<d;i++)
        a[f++]=b[i];
}
void mergesort(ll frist,ll last)
{
    ll mid=0;
    if (frist<last)
    {
        mid=(frist+last)/2;
        mergesort(frist,mid);
        mergesort(mid+1,last);
        merge_bing(frist,mid,last);
    }
}
int main()
{
    int n;
    while(cin>>n)
    {
        if(n==0)
            break;
        ll i,j;
        for(i=0;i<n;i++)
            cin>>a[i];
        cnt=0;
        mergesort(0,n-1);
        cout<<cnt<<endl;
    }
    return 0;
}

五:快速排序  O(nlogn)

快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

就是qsort 但是現在一般用sort直接呼叫函式就好

六:堆排序  O(nlogn)

n堆排序(Heapsort)是指利用堆這種資料結構所設計的一種排序演算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

void heap_sort( int arr[], int len )
{
    int i;
    /* 初始化,i從最後一個父結點開始調整 */
    for ( i = len / 2 - 1; i >= 0; i-- )
        max_heapify( arr, i, len - 1 );
    /* 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢 */
    for ( i = len - 1; i > 0; i-- )
    {
        swap( &arr[0], &arr[i] );
        max_heapify( arr, 0, i - 1 );
    }
}
void max_heapify( int arr[], int start, int end )
{
    /* 建立父結點指標和子結點指標 */
    int dad = start;
    int son = dad * 2 + 1;
    while ( son <= end )                                            /* 若子結點在指定範圍內才做比較 */
    {
        if ( son + 1 <= end && arr[son] < arr[son + 1] )  /* 先比較兩個子結點大小,選擇最大的 */
            son++;
        if ( arr[dad] > arr[son] )         /* 如果父結點大於子結點表示調整完畢,直接跳出函式 */
            return;
        else {                                                 /* 否則交換父子內容再繼續子結點和孫結點比較 */
            swap( &arr[dad], &arr[son] );
            dad = son;
            son = dad * 2 + 1;
        }
    }
}