欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2185|回復: 0
打印 上一主題 下一主題
收起左側

Linux基礎學習 收藏

[復制鏈接]
跳轉到指定樓層
樓主
ID:107189 發表于 2016-3-5 18:21 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式


                            排序

    所謂排序,就是要整理文件中的記錄,使之按關鍵字遞增(或遞減)次序排列起來。當待排序記錄的關鍵字都不相同時,排序結果是惟一的,否則排序結果不惟一。
    在待排序的文件中,若存在多個關鍵字相同的記錄,經過排序后這些具有相同關鍵字的記錄之間的相對次序保持不變,該排序方法是穩定的;若具有相同關鍵字的記錄之間的相對次序發生改變,則稱這種排序方法是不穩定的。
    要注意的是,排序算法的穩定性是針對所有輸入實例而言的。即在所有可能的輸入實例中,只要有一個實例使得算法不滿足穩定性要求,則該排序算法就是不穩定的。


一.插入排序
    插入排序的基本思想是每步將一個待排序的記錄按其排序碼值的大小,插到前面已經排好的文件中的適當位置,直到全部插入完為止。插入排序方法主要有直接插入排序和希爾排序。

①.直接插入排序(穩定)
    接插入排序的過程為:在插入第i個記錄時,R1,R2,..Ri-1已經排好序,將第i個記錄的排序碼Ki依次和R1,R2,..,Ri-1的排序碼逐個進行比較,找到適當的位置。使用直接插入排序,對于具有n個記錄的文件,要進行n-1趟排序。

代碼如下:

void Dir_Insert(int A[],int N)  //直接插入排序
{
    int j,t;
    for(int i=1;i<N;i++)
    {
        t=A[i];
        j=i-1;
        while(A[j]>t)
        {
            A[j+1]=A[j];
            j--;
        }
        A[j+1]=t;
    }
}


②.希爾排序(不穩定):
    希爾(Shell)排序的基本思想是:先取一個小于n的整數d1作為第一個增量把文件的全部記錄分成d1個組。所有距離為d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然后,取得第二個增量d2<d1重復上述的分組和排序,直至所取的增量di=1,即所有記錄放在同一組中進行直接插入排序為止。該方法實質上是一種分組插入方法。
    一般取d1=n/2,di+1=di/2。如果結果為偶數,則加1,保證di為奇數。
    希爾排序是不穩定的,希爾排序的執行時間依賴于增量序列,其平均時間復雜度為O(n^1.3).

代碼如下:

void Shell(int A[],int n)  //Shell排序
{
    int i,j,k,t;
    (n/2)%2 == 0 ? k = n/2+1 : k = n/2; //保證增量為奇數
    while(k > 0)
    {
        for(j=k;j<n; j++)
        {
            t = A[j];
            i = j - k;
            while(i>=0 && A[i]>t)
            {
                A[i+k]=A[i];
                i=i-k;
            }
            A[i+k]=t;
        }
        if(k == 1) break;
        (k/2)%2 ==0 ? k=k/2+1 : k=k/2;
    }
}


二.選擇排序
    選擇排序的基本思想是每步從待排序的記錄中選出排序碼最小的記錄,順序存放在已排序的記錄序列的后面,直到全部排完。選擇排序中主要使用直接選擇排序和堆排序。
    
①.直接選擇排序(不穩定)
    直接選擇排序的過程是:首先在所有記錄中選出序碼最小的記錄,把它與第1個記錄交換,然后在其余的記錄內選出排序碼最小的記錄,與第2個記錄交換......依次類推,直到所有記錄排完為止。
    無論文件初始狀態如何,在第i趟排序中選出最小關鍵字的記錄,需要做n-i次比較,因此,總的比較次數為n(n-1)/2=O(n^2)。當初始文件為正序時,移動次數為0;文件初態為反序時,每趟排序均要執行交換操作,總的移動次數取最大值3(n-1)。直接選擇排序的平均時間復雜度為O(n^2)。直接選擇排序是不穩定的。

代碼如下:

void Dir_Choose(int A[],int n)  //直接選擇排序
{
    int k,t;
    for(int i=0;i<n-1;i++)
    {
        k=i;
        for(int j=i+1;j<n;j++)
        {
            if(A[j]<A[k]) k=j;
        }
        if(k!=i)
        {
            t=A[i];
            A[i]=A[k];
            A[k]=t;
        }
    }
}


②.堆排序(不穩定)
    堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。n個關鍵字序列
K1,K2,...,Kn稱為堆,當且僅當該序列滿足(Ki<=K2i且Ki<=K2i+1)或(Ki>=K2i且Ki>=K2i+1),(1<=i<=n/2)。根結點(堆頂)的關鍵字是堆里所有結點關鍵字中最小者,稱為小根堆;根結點的關鍵字是堆里所有結點關鍵字中最大者,稱為大根堆。
    若將此序列所存儲的向量R[1..n]看作是一棵完全二叉樹的存儲結構,則堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉結點的關鍵字均不大于(或不小于)其左右孩子(若存在)結點的關鍵字。
    堆排序的關鍵步驟有兩個:一是如何建立初始堆;二是當堆的根結點與堆的最后一個結點交換后,如何對少了一個結點后的結點序列做調整,使之重新成為堆。堆排序的最壞時間復雜度為O(nlog2n),堆排序的平均性能較接近于最壞性能。由于建初始堆所需的比較 次數較多,所以堆排序不適宜于記錄較少的文件。堆排序是就地排序,輔助空間為O(1),它是不穩定的排序方法。

代碼略..


三.交換排序
    交換排序的基本思想是:兩兩比較待排序記錄的排序碼,并交換不滿足順序要求的那寫偶對,直到滿足條件為止。交換排序的主要方法有冒泡排序和快速排序.

①.冒泡排序(穩定的)
    冒泡排序將被排序的記錄數組R[1..n]垂直排列,每個記錄R[i]看作是重量為ki的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R;凡掃描到違反本原則的輕氣泡,就使其向上"漂浮"。如此反復進行,直到最后任何兩個氣泡都是輕者在上,重者在下為止。
    冒泡排序的具體過程如下:
    第一步,先比較k1和k2,若k1>k2,則交換k1和k2所在的記錄,否則不交換。繼續對k2和k3重復上述過程,直到處理完kn-1和kn。這時最大的排序碼記錄轉到了最后位置,稱第1次起泡,共執行n-1次比較。
    與第一步類似,從k1和k2開始比較,到kn-2和kn-1為止,共執行n-2次比較。
    依次類推,共做n-1次起泡,完成整個排序過程。
    若文件的初始狀態是正序的,一趟掃描即可完成排序。所需關鍵字比較次數為n-1次,記錄移動次數為0。因此,冒泡排序最好的時間復雜度為O(n)。
    若初始文件是反序的,需要進行n-1趟排序。每趟排序要進行n-i次關鍵字的比較(1<=i<=n-1),且每次比較都必須移動記錄三次來達到交換記錄位置。在這種情況下,比較次數達到最大值n(n-1)/2=O(n^2),移動次數也達到最大值3n(n-1)/2=O(n^2)。因此,冒泡排序的最壞時間復雜度為O(n^2)。
    雖然冒泡排序不一定要進行n-1趟,但由于它的記錄移動次數較多,故平均性能比直接插入排序要差得多。冒泡排序是就地排序,且它是穩定的。

代碼如下:

void QP(int A[],int n)  //優化的冒泡排序 
{
    int count=0,t,flag;
    for(int i=0;i<n-1;i++)
    {
        flag=0;
        for(int j=0;j<n-i;j++)
        {
            if(A[j+1]<A[j])
            {
                t=A[j];
                A[j]=A[j+1];
                A[j+1]=t;
                flag=1;
                count+=3;
            }
        }
        if(flag==0) break;
    }
}


②.快速排序:(不穩定的)
    快速排序采用了一種分治的策略,通常稱其為分治法,其基本思想是:將原問題分解為若干個規模更小但結構與原問題相似的子問題。遞歸地解這些子問題,然后將這些子問題的解組合為原問題的解。
    快速排序的具體過程如下:
    第一步,在待排序的n個記錄中任取一個記錄,以該記錄的排序碼為準,將所有記錄分成兩組,第1組各記錄的排序碼都小于等于該排序碼,第2組各記錄的排序碼都大于該排序碼,并把該記錄排在這兩組中間。
    第二步,采用同樣的方法,對左邊的組和右邊的組進行排序,直到所有記錄都排到相應的位置為止。

代碼如下:

void Quick_Sort(int A[],int low,int high)  //low和high是數組的下標
{
    if(low<high)
    {
        int temp,t=A[low];
        int l=low,h=high;
        while(l<h)
        {
            while(A[l]<t) l++;
            while(A[h]>=t) h--;
            if(h>l)
            {
                temp=A[l];
                A[l]=A[h];
                A[h]=temp;
            }
        }
        Quick_Sort(A,low,l-1);
        Quick_Sort(A,l+1,high);
    }
}


四.歸并排序
    歸并排序是將兩個或兩個以上的有序子表合并成一個新的有序表。初始時,把含有n個結點的待排序序列看作由n個長度都為1的有序子表組成,將它們依次兩兩歸并得到長度為2的若干有序子表,再對它們兩兩合并。直到得到長度為n的有序表,排序結束。
    歸并排序是一種穩定的排序,可用順序存儲結構,也易于在鏈表上實現,對長度為n的文件,需進行log2n趟二路歸并,每趟歸并的時間為O(n),故其時間復雜度無論是在最好情況下還是在最壞情況下均是O(nlog2n)。歸并排序需要一個輔助向量來暫存兩個有序子文件歸并的結果,故其輔助空間復雜度為O(n),顯然它不是就地排序。

代碼略...



五.基數排序
設單關鍵字的每個分量的取值范圍均是C0<=Kj<=Crd-1(0<=j<=rd),可能的取值個數rd稱為基數.基數的選擇和關鍵字的分解因關鍵字的類型而異.
  (1).若關鍵字是十進制整數,則按個、十等位進行分解,基數rd=10,C0=0,C9=9,d為最長整數的位數.
  (2).若關鍵字是小寫的英文字符串,則rd=26,C0='a',C25='z',d為最長字符串的長度.
  基數排序的基本思想是:從低位到高位依次對待排序的關鍵碼進行分配和收集,經過d趟分配和收集,就可以得到一個有序序列.





按平均時間將排序分為四類:

(1)平方階(O(n2))排序
     一般稱為簡單排序,例如直接插入、直接選擇和冒泡排序;

(2)線性對數階(O(nlgn))排序
     如快速、堆和歸并排序;

(3)O(n1+£)階排序
     £是介于0和1之間的常數,即0<£<1,如希爾排序;

(4)線性階(O(n))排序
     如基數排序。

各種排序方法比較
     簡單排序中直接插入最好,快速排序最快,當文件為正序時,直接插入和冒泡均最佳。

影響排序效果的因素
    因為不同的排序方法適應不同的應用環境和要求,所以選擇合適的排序方法應綜合考慮下列因素:
  ①待排序的記錄數目n;
  ②記錄的大小(規模);
  ③關鍵字的結構及其初始狀態;
  ④對穩定性的要求;
  ⑤語言工具的條件;
  ⑥存儲結構;
  ⑦時間和輔助空間復雜度等。

不同條件下,排序方法的選擇

(1)若n較小(如n≤50),可采用直接插入或直接選擇排序。
     當記錄規模較小時,直接插入排序較好;否則因為直接選擇移動的記錄數少于直接插人,應選直接選擇排序為宜。
(2)若文件初始狀態基本有序(指正序),則應選用直接插人、冒泡或隨機的快速排序為宜;
(3)若n較大,則應采用時間復雜度為O(nlgn)的排序方法:快速排序、堆排序或
歸并排序。
    快速排序是目前基于比較的內部排序中被認為是最好的方法,當待排序的關鍵字是隨機分布時,快速排序的平均時間最短;
    堆排序所需的輔助空間少于快速排序,并且不會出現快速排序可能出現的最壞情況。這兩種排序都是不穩定的。
    若要求排序穩定,則可選用歸并排序。但從單個記錄起進行兩兩歸并的  排序算法并不值得提倡,通常可以將它和直接插入排序結合在一起使用。先利用直接插入排序求得較長的有序子文件,然后再兩兩歸并之。因為直接插入排序是穩定的,所以改進后的歸并排序仍是穩定的。


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表