每日演算法 歸併排序演算法

2022-08-09 02:18:15 字數 3535 閱讀 3278

歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(divide and conquer)的乙個非常典型的應用。歸併排序是一種穩定的排序方法。

將已有序的子串行合併,得到完全有序的序列;即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為2-路歸併。

歸併排序具體演算法描述如下(遞迴版本):

1、divide: 把長度為n的輸入序列分成兩個長度為n/2的子串行。

2、conquer: 對這兩個子串行分別採用歸併排序。

3、combine: 將兩個排序好的子串行合併成乙個最終的排序序列。

歸併排序的效率是比較高的,設數列長為n,將數列分開成小數列一共要logn步,每步都是乙個合併有序數列的過程,時間複雜度可以記為o(n),故一共為o(nlogn)。因為歸併排序每次都是在相鄰的資料中進行操作,所以歸併排序在o(nlogn)的幾種排序方法(快速排序,歸併排序,希爾排序,堆排序)也是效率比較高的。

//將有二個有序數列a[first...mid]和a[mid...last]合併。  

void mergearray(int a, int first, int mid, int last, int temp)

while (i <= m)

temp[k++] = a[i++];

while (j <= n)

temp[k++] = a[j++];

for (i = 0; i < k; i++)

a[first + i] = temp[i];

} //遞迴地完成歸併排序

void mergesort(int a, int first, int last, int temp)

}

歸併排序本身作為一種高效的排序演算法,也是常會被問到的。尤其是歸併排序體現的遞迴思路很重要,在遞迴的過程中可以完成很多事情,很多演算法題也是使用的這個思路,可見下面7)部分的筆試面試演算法題。

例題1、題目輸入乙個陣列,陣列元素的大小在0->999.999.999的範圍內,元素個數為0-500000範圍。題目要求通過相鄰的元素的交換,使得輸入的陣列變為有序,要求輸出交換的次數

這題求解的其實就是乙個逆序對。我們回想一下歸併排序的過程:

歸併排序是用分治思想,分治模式在每一層遞迴上有三個步驟:

分解:將n個元素分成個含n/2個元素的子串行。

解決:用合併排序法對兩個子串行遞迴的排序。

合併:合併兩個已排序的子串行已得到排序結果。

在歸併排序演算法中稍作修改,就可以在n log n的時間內求逆序對。

將陣列a[1...size],劃分為a[1...mid] 和 a[mid+1...size].那麼逆序對數的個數為 f(1, size) = f(1, mid) + f(mid+1, size) + s(1, mid, size),這裡s(1, mid, size)代表左值在[1---mid]中,右值在[mid+1, size]中的逆序對數。由於兩個子串行本身都已經排序,所以查詢起來非常方便。

**如下:

#include#includeusing namespace std;  

void printarray(int arry,int len)

else

} cout<

while(j>mid)

//將臨時陣列中的元素寫回到原陣列當中去。

for(i=0;i例題2、有10個檔案,每個檔案1g,每個檔案的每一行存放的都是使用者的query,每個檔案的query都可能重複。要求你按照query的頻度排序。

1、hash對映:順序讀取10個檔案,按照hash(query)%10的結果將query寫入到另外10個檔案(記為)中。這樣新生成的檔案每個的大小大約也1g(假設hash函式是隨機的)。

2、hash統計:找一台內存在2g左右的機器,依次對用hash_map(query, query_count)來統計每個query出現的次數。注:hash_map(query,query_count)是用來統計每個query的出現次數,不是儲存他們的值,出現一次,則count+1。

3、堆/快速/歸併排序:利用快速/堆/歸併排序按照出現次數進行排序。將排序好的query和對應的query_cout輸出到檔案中。這樣得到了10個排好序的檔案(記為)。對這10個檔案進行歸併排序(內排序與外排序相結合)。

例題3、歸併乙個左右兩邊分別排好序的陣列,空間複雜度要求o(1)。

使用原地歸併,能夠讓歸併排序的空間複雜度降為o(1),但是速度上會有一定程度的下降。**如下:

#include#include#include#includeusing namespace std;

void insert_sort(int arr,int n)

arr[j+1]=val;

} } void aux_merge(int arr,int n,int m,int aux) else

} else

break;

} else

dst--;

} } void local_merge(int arr,int n)

for(int i=0;i

aux_merge(arr+i*m,m,m,arr+(k-1)*m);

int s=n%m+m;

insert_sort(arr+(n-2*s),2*s);

aux_merge(arr,n-2*s,s,arr+(k-1)*m);

insert_sort(arr+(k-1)*m,s);

} void local_merge_sort(int arr,int n)

local_merge_sort(arr,n/2);

local_merge_sort(arr+n/2,n-n/2);

local_merge(arr,n);

} void merge_sort(int arr,int temp,int n)

merge_sort(arr,temp,n/2);

merge_sort(arr+n/2,temp,n-n/2);

for(int i=0;i

temp[i]=arr[i];

for(int i=n/2;i

temp[n+n/2-i-1]=arr[i];

int left=0,right=n-1;

for(int i=0;i

if(temp[left]

arr[i]=temp[left++];

else

arr[i]=temp[right--];

} const int n=2000000;

int arr1[n],arr2[n];

int temp[n];

int main()

歸併演算法 歸併排序

歸併演算法 歸併排序 這周需要用到歸併演算法,於是找了找相關的資料,整理如下 歸併排序 merge sort 是利用 歸併 技術來進行排序。歸併是指將若干個已排序的子檔案合併成乙個有序的檔案。兩路歸併演算法 1 演算法基本思路 設兩個有序的子檔案 相當於輸入堆 放在同一向量中相鄰的位置上 r low...

歸併排序演算法

include stdafx.h include include include 合併兩段已經排好序的列表 void merge int list int mergelist int left int mid int right else if i mid else 將列表list按照seglen分...

歸併排序演算法

這個演算法感覺比插入難理解一些,下面說說我的理解 歸併排序的步驟 1.把長度為n的序列分為兩個長度為n 2的子串行 2.對這兩個子串行分別採用歸併排序 3.將兩個子串行合併成乙個最終的排序序列 通過步驟2可看到 在歸併排序中又用了歸併排序,可見這是乙個遞迴的過程。例如乙個陣列 a 8 下面採用遞迴排...