歸并算法

歸并排序法 :

百科鏈接

說(shuō)明:
歸并排序比較占用內(nèi)存鼠锈,但卻是一種效率高而且穩(wěn)定的算法寒砖。

歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用佛嬉。將已有序的子序列合并蛉迹,得到完全有序的序列稠诲;即先使每個(gè)子序列有序舵匾,再使子序列段間有序诬乞。若將兩個(gè)有序表合并成一個(gè)有序表册赛,稱為二路歸并
歸并過(guò)程為:比較a[i]和a[j]的大小震嫉,若a[i]≤a[j]森瘪,則將第一個(gè)有序表中的元素a[i]復(fù)制到r[k]中,并令i和k分別加上1票堵;否則將第二個(gè)有序表中的元素a[j]復(fù)制到r[k]中扼睬,并令j和k分別加上1,如此循環(huán)下去悴势,直到其中一個(gè)有序表取完窗宇,然后再將另一個(gè)有序表中剩余的元素復(fù)制到r中從下標(biāo)k到下標(biāo)t的單元。歸并排序的算法我們通常用遞歸實(shí)現(xiàn)特纤,先把待排序區(qū)間[s,t]以中點(diǎn)二分军俊,接著把左邊子區(qū)間排序,再把右邊子區(qū)間排序捧存,最后把左區(qū)間和右區(qū)間用一次歸并操作合并成有序的區(qū)間[s,t]粪躬。
操作:
歸并操作(merge)担败,也叫歸并算法,指的是將兩個(gè)順序序列合并成一個(gè)順序序列的方法镰官。
如 設(shè)有數(shù)列{6提前,202,100泳唠,301狈网,38,8笨腥,1}
初始狀態(tài):6,202,100,301,38,8孙援,1
第一次歸并后:{6,202},{100,301},{8,38},{1},比較次數(shù):3扇雕;
第二次歸并后:{6,100,202,301},{1,8,38}窥摄,比較次數(shù):4镶奉;
第三次歸并后:{1,6,8,38,100,202,301},比較次數(shù):4;
總的比較次數(shù)為:3+4+4=11,崭放;
逆序數(shù)為14哨苛;
描述:
歸并操作的工作原理如下:

  • 第一步:申請(qǐng)空間,使其大小為兩個(gè)已經(jīng)排序序列之和币砂,該空間用來(lái)存放合并后的序列
  • 第二步:設(shè)定兩個(gè)指針建峭,最初位置分別為兩個(gè)已經(jīng)排序序列的起始位置
  • 第三步:比較兩個(gè)指針?biāo)赶虻脑兀x擇相對(duì)小的元素放入到合并空間决摧,并移動(dòng)指針到下一位置
  • 重復(fù)步驟3直到某一指針超出序列尾
    將另一序列剩下的所有元素直接復(fù)制到合并序列尾
    Java語(yǔ)言
package algorithm;
public class MergeSort {
    // private static long sum = 0;
    /**
     * <pre>
     * 二路歸并
     * 原理:將兩個(gè)有序表合并和一個(gè)有序表
     * </pre>
     * 
     * @param a
     * @param s
     * 第一個(gè)有序表的起始下標(biāo)
     * @param m
     * 第二個(gè)有序表的起始下標(biāo)
     * @param t
     * 第二個(gè)有序表的結(jié)束小標(biāo)
     * 
     */
    private static void merge(int[] a, int s, int m, int t) {
        int[] tmp = new int[t - s + 1];
        int i = s, j = m, k = 0;
        while (i < m && j <= t) {
            if (a[i] <= a[j]) {
                tmp[k] = a[i];
                k++;
                i++;
            } else {
                tmp[k] = a[j];
                j++;
                k++;
            }
        }
        while (i < m) {
            tmp[k] = a[i];
            i++;
            k++;
        }
        while (j <= t) {
            tmp[k] = a[j];
            j++;
            k++;
        }
        System.arraycopy(tmp, 0, a, s, tmp.length);
    }
    /**
     * 
     * @param a
     * @param s
     * @param len
     * 每次歸并的有序集合的長(zhǎng)度
     */
    public static void mergeSort(int[] a, int s, int len) {
        int size = a.length;
        int mid = size / (len << 1);
        int c = size & ((len << 1) - 1);
        // -------歸并到只剩一個(gè)有序集合的時(shí)候結(jié)束算法-------//
        if (mid == 0)
            return;
        // ------進(jìn)行一趟歸并排序-------//
        for (int i = 0; i < mid; ++i) {
            s = i * 2 * len;
            merge(a, s, s + len, (len << 1) + s - 1);
        }
        // -------將剩下的數(shù)和倒數(shù)一個(gè)有序集合歸并-------//
        if (c != 0)
            merge(a, size - c - 2 * len, size - c, size - 1);
        // -------遞歸執(zhí)行下一趟歸并排序------//
        mergeSort(a, 0, 2 * len);
    }
    public static void main(String[] args) {
        int[] a = new int[] { 4, 3, 6, 1, 2, 5 };
        mergeSort(a, 0, 1);
        for (int i = 0; i < a.length; ++i) {
            System.out.print(a[i] + " ");
        }
    }
}

歸并算法

定義

所謂歸并排序是指將兩個(gè)或兩個(gè)以上有序的數(shù)列(或有序表)亿蒸,合并成一個(gè)仍然有序的數(shù)列(或有序表)。這樣的排序方法經(jīng)常用于多個(gè)有序的數(shù)據(jù)文件歸并成一個(gè)有序的數(shù)據(jù)文件掌桩。歸并排序的算法比較簡(jiǎn)單边锁。
基本思想方法:
(1)假設(shè)已經(jīng)有兩個(gè)有序數(shù)列,分別存放在兩個(gè)數(shù)組s波岛,r中茅坛;并設(shè)i,j分別為指向數(shù)組的第一個(gè)單元的下標(biāo)则拷;s有n個(gè)元素贡蓖,r有m個(gè)元素。
(2)再另設(shè)一個(gè)數(shù)組a煌茬,k指向該數(shù)組的第一個(gè)單元下標(biāo)斥铺。
(3)算法分析(過(guò)程):

proceduremerge(s,r,a,i,j,k);
begin
i1:=i;
j1:=j;
k1:=k;
while(i1<n)and(j1<m)do
ifs[i1]<=r[j1]then
begin
a[k]:=s[i1];
i1:=i1+1;
k:=k+1;
end
else
begin
a[k]:=r[j1];
j1:=j1+1;
k:=k+1;
end;
whilei1<=ndo
begin
a[k]:=s[i1];
i1:=i1+1;
k:=k+1;
end;
whilej1<=mdo
begin
a[k]:=r[j1];
j1:=j1+1;
k:=k+1;
end;
end;

完整的C++源代碼

#include<iostream.h>
voidMerge(intr[],intr1[],ints,intm,intt){
inti=s;
intj=m+1;
intk=s;
while(i<=m&&j<=t){
if(r[i]<=r[j])
r1[k++]=r[i++];
else
r1[k++]=r[j++];
}
if(i<=m)
while(i<=m)
r1[k++]=r[i++];
else
while(j<=t)
r1[k++]=r[j++];
for(intn=s;n<=t;n++)
r[n]=r1[n];
}
 
voidMergeSort(intr[],intr1[],ints,intt){
if(s<t){
intm=(s+t)/2;
MergeSort(r,r1,s,m);
MergeSort(r,r1,m+1,t);
Merge(r,r1,s,m,t);
}
}
voidmain(){
intr[8]={10,3,5,1,9,34,54,565},r1[8];
MergeSort(r,r1,0,7);
for(intq=0;q<8;q++)
cout<<""<<r[q];
return0;
}

歸并排序的實(shí)現(xiàn)方法:
1.自底向上算法

#include<stdio.h>
#include<time.h>
voidMerge(int*a,intlow,intmid,inthigh){
inti=low,j=mid+1,k=0;
int*temp=(int*)malloc((high-low+1)*sizeof(int));
while(i<=mid&&j<=high)
a[i]<=a[j]?(temp[k++]=a[i++]):(temp[k++]=a[j++]);
while(i<=mid)
temp[k++]=a[i++];
while(j<=high)
temp[k++]=a[j++];
memcpy(a+low,temp,(high-low+1)*sizeof(int));
free(temp);
}
voidMergeSort(int*a,intn){
intlength;
for(length=1;length<n;length*=2){
inti;
for(i=0;i+2*length-1<=n-1;i+=2*length)
Merge(a,i,i+length-1,i+2*length-1);
if(i+length<=n-1)//尚有兩個(gè)子文件宣旱,其中后一個(gè)長(zhǎng)度小于length
 Merge(a,i,i+length-1,n-1);
}
}
intmain(){
intn;
cin>>n;
int*data=new
int[n];
if(!data)
exit(1);
intk=n;
while(k--){
cin>>data[n-k-1];
}
clock_ts=clock();
MergeSort(data,n);
clock_te=clock();
k=n;
while(k--){
cout<<data[n-k-1]<<'';
}
cout<<endl;
cout<<"thealgrothemused"<<e-s<<"miliseconds."<<endl;
deletedata;
return0;
}

2.自頂向下

voidMerge(intr[],intr1[],ints,intm,intt){
inti=s;
intj=m+1;
intk=s;
while(i<=m&&j<=t){
if(r[i]<=r[j])
r1[k++]=r[i++];
else
r1[k++]=r[j++];
}
while(i<=m)
r1[k++]=r[i++];
while(j<=t)
r1[k++]=r[j++];
for(intl=0;l<8;l++)
r[l]=r1[l];
}
 
voidMergeSort(intr[],intr1[],ints,intt){
if(s==t)
;
else{
intm=(s+t)/2;
MergeSort(r,r1,s,m);
MergeSort(r,r1,m+1,t);
Merge(r,r1,s,m,t);
}
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仅父,一起剝皮案震驚了整個(gè)濱河市叛薯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笙纤,老刑警劉巖耗溜,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異省容,居然都是意外死亡抖拴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)腥椒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)阿宅,“玉大人,你說(shuō)我怎么就攤上這事笼蛛∪鞣牛” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵滨砍,是天一觀的道長(zhǎng)往湿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)惋戏,這世上最難降的妖魔是什么领追? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮响逢,結(jié)果婚禮上绒窑,老公的妹妹穿的比我還像新娘。我一直安慰自己舔亭,他們只是感情好些膨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著钦铺,像睡著了一般傀蓉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上职抡,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天葬燎,我揣著相機(jī)與錄音,去河邊找鬼缚甩。 笑死谱净,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的擅威。 我是一名探鬼主播壕探,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼郊丛!你這毒婦竟也來(lái)了李请?” 一聲冷哼從身側(cè)響起瞧筛,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎导盅,沒(méi)想到半個(gè)月后较幌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡白翻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年乍炉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滤馍。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岛琼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巢株,到底是詐尸還是另有隱情槐瑞,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布阁苞,位于F島的核電站随珠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏猬错。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一茸歧、第九天 我趴在偏房一處隱蔽的房頂上張望倦炒。 院中可真熱鬧,春花似錦软瞎、人聲如沸逢唤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鳖藕。三九已至,卻和暖如春只锭,著一層夾襖步出監(jiān)牢的瞬間著恩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工蜻展, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喉誊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓纵顾,卻偏偏與公主長(zhǎng)得像伍茄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子施逾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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

  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個(gè)記錄插入到已排序好...
    依依玖玥閱讀 1,243評(píng)論 0 2
  • 概述 排序有內(nèi)部排序和外部排序敷矫,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序例获,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,168評(píng)論 0 52
  • 概述:排序有內(nèi)部排序和外部排序曹仗,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序榨汤,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    每天刷兩次牙閱讀 3,729評(píng)論 0 15
  • 概述排序有內(nèi)部排序和外部排序整葡,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序件余,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部的...
    Luc_閱讀 2,259評(píng)論 0 35
  • 歸并排序(Merge sort遭居,臺(tái)灣譯作:合并排序)是建立在歸并操作上的一種有效的排序算法啼器。歸并算法的中心是歸并兩...
    Bloo_m閱讀 371評(píng)論 0 1