Chapter1 Merge Sort

一辕狰、合并排序

  • 基本思想:把待排序列分解成兩個(gè)規(guī)模大致相等的子序列勋眯。如果不易解決浪箭,再將得到的子序列繼續(xù)分解穗椅,直到子序列中包含的元素個(gè)數(shù)為1.因?yàn)閱蝹€(gè)元素的序列本身有序,此時(shí)便可以進(jìn)行合并奶栖,從而得到一個(gè)完整的有序序列

  • 算法思想:基于分治策略

    • 分解:將待排序列分成規(guī)模大致相等的兩個(gè)子序列
    • 治理:對(duì)兩個(gè)子序列進(jìn)行合并排序
    • 合并:將排好序的的有序子序列進(jìn)行合并匹表,得到最終的有序序列
  • 時(shí)間復(fù)雜度:n log n

二、AcWing模板

模板題:AcWing 787. 歸并排序

//
// Created by zk on 2021/6/1.
//
#include <iostream>
using namespace std;

const int N = 1000010;
int n;
int q[N], tmp[N];

void merge_sort(int q[], int l, int r){
    if (l >= r) return;

    int mid = l + r >> 1;

    merge_sort(q, l, mid);
    merge_sort(q, mid+1, r);

    int k = 0;
    int i = l;
    int j = mid + 1;
    while(i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k++] = q[i++];
        else tmp[k ++] = q[j++];

    while(i <= mid) tmp[k ++] = q[i++];
    while(j <= r) tmp[k++] = q[j++];

    for(i=l, j=0; i<=r; i++, j++) q[i] = tmp[j];
}

int main(){
    scanf("%d", &n);
    for(int i=0; i<n; i++) scanf("%d", &q[i]);

    merge_sort(q, 0, n-1);

    for(int i=0; i<n; i++) printf("%d ", q[i]);

    return 0;
}


三驼抹、趣學(xué)數(shù)據(jù)結(jié)構(gòu)版

#include<iostream>
using namespace std;

void Merge(int A[],int low,int mid,int high)//合并函數(shù)
{
    int *B=new int[high-low+1];//申請(qǐng)一個(gè)輔助數(shù)組
    int i=low,j=mid+1,k=0;
    while(i<=mid&&j<=high) {//按從小到大存放到輔助數(shù)組B[]中
        if(A[i]<=A[j])
            B[k++]=A[i++];
        else
            B[k++]=A[j++];
    }
    while(i<=mid) B[k++]=A[i++];//將數(shù)組中剩下的元素放置B中
    while(j<=high) B[k++]=A[j++];
    for(i=low,k=0;i<=high;i++)
        A[i]=B[k++];
    delete []B;//釋放空間
}

void MergeSort(int A[],int low,int high)//合并排序
{
    if(low<high)
    {
        int mid=(low+high)/2;//取中點(diǎn)
        MergeSort(A,low,mid);//對(duì)A[low:mid]中的元素合并排序
        MergeSort(A,mid+1,high);//對(duì)A[mid+1:high]中的元素合并排序
        Merge(A,low,mid,high);//合并
    }
}
int main()
{
    int n, A[100];
    cout<<"請(qǐng)輸入數(shù)列中的元素個(gè)數(shù)n為:"<<endl;
    cin>>n;
    cout<<"請(qǐng)依次輸入數(shù)列中的元素:"<<endl;
    for(int i=0;i<n;i++)
       cin>>A[i];
    MergeSort(A,0,n-1);
    cout<<"合并排序結(jié)果:"<<endl;
    for(int i=0;i<n;i++)
       cout<<A[i]<<" ";
    cout<<endl;
    return 0;
}

四桑孩、陳越版

更加專業(yè)

  1. 遞歸實(shí)現(xiàn)
/* 歸并排序 - 遞歸實(shí)現(xiàn) */

/* L = 左邊起始位置, R = 右邊起始位置, RightEnd = 右邊終點(diǎn)位置*/
void Merge( ElementType A[], ElementType TmpA[], int L, int R, int RightEnd )
{ /* 將有序的A[L]~A[R-1]和A[R]~A[RightEnd]歸并成一個(gè)有序序列 */
     int LeftEnd, NumElements, Tmp;
     int i;
     
     LeftEnd = R - 1; /* 左邊終點(diǎn)位置 */
     Tmp = L;         /* 有序序列的起始位置 */
     NumElements = RightEnd - L + 1;
     
     while( L <= LeftEnd && R <= RightEnd ) {
         if ( A[L] <= A[R] )
             TmpA[Tmp++] = A[L++]; /* 將左邊元素復(fù)制到TmpA */
         else
             TmpA[Tmp++] = A[R++]; /* 將右邊元素復(fù)制到TmpA */
     }

     while( L <= LeftEnd )
         TmpA[Tmp++] = A[L++]; /* 直接復(fù)制左邊剩下的 */
     while( R <= RightEnd )
         TmpA[Tmp++] = A[R++]; /* 直接復(fù)制右邊剩下的 */
         
     for( i = 0; i < NumElements; i++, RightEnd -- )
         A[RightEnd] = TmpA[RightEnd]; /* 將有序的TmpA[]復(fù)制回A[] */
}

void Msort( ElementType A[], ElementType TmpA[], int L, int RightEnd )
{ /* 核心遞歸排序函數(shù) */ 
     int Center;
     
     if ( L < RightEnd ) {
          Center = (L+RightEnd) / 2;
          Msort( A, TmpA, L, Center );              /* 遞歸解決左邊 */ 
          Msort( A, TmpA, Center+1, RightEnd );     /* 遞歸解決右邊 */  
          Merge( A, TmpA, L, Center+1, RightEnd );  /* 合并兩段有序序列 */ 
     }
}

void MergeSort( ElementType A[], int N )
{ /* 歸并排序 */
     ElementType *TmpA;
     TmpA = (ElementType *)malloc(N*sizeof(ElementType));
     
     if ( TmpA != NULL ) {
          Msort( A, TmpA, 0, N-1 );
          free( TmpA );
     }
     else printf( "空間不足" );
}
  1. 循環(huán)實(shí)現(xiàn)
/* 歸并排序 - 循環(huán)實(shí)現(xiàn) */
/* 這里Merge函數(shù)在遞歸版本中給出 */

/* length = 當(dāng)前有序子列的長(zhǎng)度*/
void Merge_pass( ElementType A[], ElementType TmpA[], int N, int length )
{ /* 兩兩歸并相鄰有序子列 */
     int i, j;
      
     for ( i=0; i <= N-2*length; i += 2*length )
         Merge( A, TmpA, i, i+length, i+2*length-1 );
     if ( i+length < N ) /* 歸并最后2個(gè)子列*/
         Merge( A, TmpA, i, i+length, N-1);
     else /* 最后只剩1個(gè)子列*/
         for ( j = i; j < N; j++ ) TmpA[j] = A[j];
}

void Merge_Sort( ElementType A[], int N )
{ 
     int length; 
     ElementType *TmpA;
     
     length = 1; /* 初始化子序列長(zhǎng)度*/
     TmpA = malloc( N * sizeof( ElementType ) );
     if ( TmpA != NULL ) {
          while( length < N ) {
              Merge_pass( A, TmpA, N, length );
              length *= 2;
              Merge_pass( TmpA, A, N, length );
              length *= 2;
          }
          free( TmpA );
     }
     else printf( "空間不足" );
}

五、 可視化展示

  1. Data Structure Visualization: https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
    merge sort
  1. VisuAlgo: https://visualgo.net/zh
    merge sort
  1. algorithm-visualizer: https://algorithm-visualizer.org/
    merge sort
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末框冀,一起剝皮案震驚了整個(gè)濱河市流椒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌明也,老刑警劉巖宣虾,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惯裕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绣硝,警方通過(guò)查閱死者的電腦和手機(jī)蜻势,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)鹉胖,“玉大人握玛,你說(shuō)我怎么就攤上這事「Σぃ” “怎么了挠铲?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)寂诱。 經(jīng)常有香客問(wèn)我拂苹,道長(zhǎng),這世上最難降的妖魔是什么痰洒? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任瓢棒,我火速辦了婚禮,結(jié)果婚禮上丘喻,老公的妹妹穿的比我還像新娘脯宿。我一直安慰自己,他們只是感情好泉粉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布嗅绰。 她就那樣靜靜地躺著,像睡著了一般搀继。 火紅的嫁衣襯著肌膚如雪窘面。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天叽躯,我揣著相機(jī)與錄音财边,去河邊找鬼。 笑死点骑,一個(gè)胖子當(dāng)著我的面吹牛酣难,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播黑滴,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼憨募,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了袁辈?” 一聲冷哼從身側(cè)響起菜谣,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后尾膊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體媳危,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年冈敛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了待笑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抓谴,死狀恐怖暮蹂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情癌压,我是刑警寧澤椎侠,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站措拇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏慎宾。R本人自食惡果不足惜丐吓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趟据。 院中可真熱鬧券犁,春花似錦、人聲如沸汹碱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咳促。三九已至稚新,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跪腹,已是汗流浹背褂删。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冲茸,地道東北人屯阀。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像轴术,于是被迫代替她去往敵國(guó)和親难衰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容