1. 程式人生 > >【分治法】合併排序及C++原始碼

【分治法】合併排序及C++原始碼

(1)合併排序是成功應用分治技術的一個完美例子。

對於一個需要排列的陣列A[0..n-1],合併排序將它一分為二:A[0..[n/2]-1]和A[[n/2]..n-1],並對每個子陣列遞迴排序,然後把這個排好序的子數組合併為一個有序陣列。

Mergesort(A[0..n-1])
// 遞迴呼叫 mergesort來對陣列A[0..n-1]排序
// 輸入:一個可排序陣列A[0..n-1]
// 輸出:非降序排列的陣列A[0..n-1]
if n>1
   copy A[0..[n/2]-1] to B[0..[n/2]-1]
   copy A[[n/2]..n-1] to C[0..[n/2]-1]
    Mergesort(B[0
..[n/2]-1])
Mergesort(C[0..[n/2]-1]) Merge(B,C,A)

(2)對兩個有序陣列的合併採用以下演算法:

①初始狀態下,兩個指標(陣列下標)分別指向兩個待合併陣列的第一個元素。

②然後比較這兩個陣列的大小,將較小的元素新增到一個新建立的陣列中。

③接著,被複制的陣列中的指標後移,指向該較小元素的後繼元素。

(上述操作一直持續到兩個陣列中的一個被處理完為止。然後在未處理完的陣列中,剩下的元素被複制到新陣列的尾部)

Merge(B[0..p-1],C[0..q-1],A[0..p+q-1])
// 將兩個有序數組合併為一個有序陣列
// 輸入:兩個有序陣列B[0..p-1]和C[0..q-1]
// 輸出:A[0..p+q-1]中已經有序存放了B和C中的元素 i<-0;j<-0;k<-0 while i<p and j<q do if B[i]<=C[j] A[k]<-B[i];i<-i+1 else A[k]<-C[j];j<-j+1 k<-k+1 if i=p copy C[j..q-1]to A[k..p+q-1] else copy B[i..p-1]to A[k..p+q-1]

(3)下圖演示的是用合併排序演算法對數列54,24,50,46,84,49,20,60進行排序的操作過程。

這裡寫圖片描述

(4)合併演算法效率

合併排序在最壞情況下的鍵值比較次數十分接近於任何基於比較的排序演算法在理論上能夠達到的最少次數。合併排序的主要缺點就是該演算法需要線性的額外空間。雖然合併也能做到“在位”,但會導致演算法過於複雜。而且,因為它的增長次數具有一個很大的常係數,所以在位的合併排序演算法只具有理論上的意義。

當n>1時,C(n)=2C(n/2)+Cmerge(n),

C(1)=0,

對於最壞情況Cmerge(n)=n-1

當n>1時,Cworst(n)=nlog②n-n+1

(5)C++原始碼實現

#include <iostream>
using namespace std;
void Merge(int a[],int b[],int l,int m,int r)
{
 int i=l,j=m+1,k=l;
    while ((i<=m)&&(j<=r))
  if (a[i]<=a[j])b[k++]=a[i++];
  else b[k++]=a[j++];
  if (i>m)for (int q=j;q<=r;q++)
   b[k++]=a[q];
  else for (int q=i;q<=m;q++)b[k++]=a[q];

}
void Copy(int a[],int b[],int s,int n)
{
 for(int i=s;i<=n;i++)
  a[i]=b[i];
}
void MergeSort(int a[],int left,int right)
{   int i;
 if(left<right)
 {i=(left+right)/2;
 int b[100];
 MergeSort(a,left,i);
 MergeSort(a,i+1,right);
    Merge(a,b,left,i,right);
 Copy(a,b,left,right);}
}
int main()
{   int t;
cin>>t;
while (t--)
{int a[100];
 int n,i;
 cin>>n;
 for ( i=0;i<n;i++)
  cin>>a[i];
 MergeSort(a,0,n-1);

   for ( i=0;i<n;i++)
  cout<<a[i]<<' ';
   cout<<endl;
}
   return 0;
}

相關推薦

治法合併排序C++原始碼

(1)合併排序是成功應用分治技術的一個完美例子。 對於一個需要排列的陣列A[0..n-1],合併排序將它一分為二:A[0..[n/2]-1]和A[[n/2]..n-1],並對每個子陣列遞迴排序,然後把這個排好序的子數組合併為一個有序陣列。 Mergeso

治法合併排序C實現)

#include <stdio.h> void merge(int a[],int p,int q,int r) { int n1=q-p+1,n2=r-q; int

治法線性時間選擇(轉)

算法思路 ont 位置 劃分 得到 子數組 als lena part 轉自:http://blog.csdn.net/liufeng_king/article/details/8480430 線性時間選擇問題:給定線性序集中n個元素和一個整數k,1≤k≤n,要求找出這n

治法最接近點對問題(轉)

線性 sig 2個 線性時間選擇 i++ srand 排序算法 esp 坐標 轉自:http://blog.csdn.net/liufeng_king/article/details/8484284 問題場景:在應用中,常用諸如點、圓等簡單的幾何對象代表現實世界中的實體。在

演算法導論 第二章:演算法入門 筆記 (插入排序、迴圈不變式、演算法分析、最好和最壞時間複雜度、選擇排序治法合併排序

插入排序: 排序問題的定義如下: 輸入:N個數{a1, a2,..., an }。 輸出:輸入序列的一個排列{a'1 ,a'1 ,...,a'n },使得a'n <=a' n<=...<

演算法導論筆記治法最近點對問題

尋找最近點對 目錄 尋找最近點對 問題分析 分治法 時間複雜度 題目:在一個 n≥2 個點的集合 Q 中尋找距離最近的點對 問題分析 首先很容易想到暴力破解的方法,但是需要 O(n2) 的時間複雜度,所以考慮使用分治法,但

Java練習:治法合併排序(merge Sort)

分而治之(divide-and-conquer)是一種古老但實用的策略、普適性的問題求解策略。本質上,分而治之策略是將整體分解成部分的思想。 按照系統科學的觀點,該策略僅適用於線性系統——整體正好對於部分之和。 (兩路)合併排序遵循分治法的三個步驟,其操作如下: (1

治法合併排序演算法理解介紹

    複習分治法,藉著這個機會將用到分治法的合併排序和快速排序演算法好好梳理一下並作出總結。     分治法求解問題的三要素是分解、求解、合併。分解是指將一個難以直接求解的複雜問題按照某種方式分解成若干個規模較小、相互獨立且和原問題型別相同的子問題,求解是指子問題分解至可

0007演算法筆記——治法最接近點對問題

問題場景:在應用中,常用諸如點、圓等簡單的幾何物件代表現實世界中的實體。在涉及這些幾何物件的問題中,常需要了解其鄰域中其他幾何物件的資訊。例如,在空中交通控制問題中,若將飛機作為空間中移動的一個點來看待,則具有最大碰撞危險的2架飛機,就是這個空間中最接近的一對點。這類問題是

0008演算法筆記——治法迴圈賽事日程表

問題描述:      設有n=2^k個運動員要進行網球迴圈賽。現要設計一個滿足以下要求的比賽日程表: (1)每個選手必須與其他n-1個選手各賽一次;      (2)每個選手一天只能參賽一次;      (3)迴圈賽在n-1天內結束。      請按此要求將比賽日程表

治法最接近點對問題——Java 實現

問題描述:        給定平面上n個點,找其中的一對點,使得在n個點組成的所有點對中,該點對間的距離最小。        注: a、嚴格地講,最接近點對可能多餘1對,為簡單起見,只找其中的1對作為問題的解。 b、一個簡單的演算法是——只要將每一個點與其他 n

治法迴圈賽事日程表

原文地址:http://blog.csdn.net/liufeng_king/article/details/8488421 問題描述:      設有n=2^k個運動員要進行網球迴圈賽。現要設計一個滿足以下要求的比賽日程表: (1)每個選手必須與其他n-1個選手各賽

特徵匹配SIFT原理與C原始碼剖析

     SIFT的原理已經有很多大牛的部落格上做了解析,本文重點將以Rob Hess等人用C實現的程式碼做解析,結合程式碼SIFT原理會更容易理解。一些難理解點的用了☆標註。       歡迎大家批評指正! 轉載請註明出處:http://blog.csdn.net/l

治法合併排序C++)

#include<iostream> #include<time.h> #include<stdlib.h> using namespace std; // 合併函式 void merge(int *arr, int

最全經典排序算法(C語言)

排好序 而不是 lock wap 循環 而且 -s 關鍵字 void 本文章包括所有基本排序算法(和其中一些算法的改進算法): 直接插入排序、希爾排序、直接選擇排序、堆排序、冒泡排序、快速排序、歸並排序、基數排序。 算法復雜度比較: 算法分類 一、直接插入排序 一個

排序選擇排序C++實現

temp esp col rgb 結果 pac strong emp 元素 # 基本思想 每一趟從待排序的數據元素中選擇最小(或最大)的一個元素作為首元素,直到所有元素排完為止。排序實例初始關鍵字 [49 38 65 97 76 13 27 49]第一趟排序後 13

排序演算法歸併排序C++)

歸併排序的遞迴實現 C++ class MergeSort { public: int* mergeSort(int* A, int n) { // write code he

Lintcode合併排序陣列&& 合併排序陣列 II

題目描述:合併兩個排序的整數陣列A和B變成一個新的陣列。 注意事項 你可以假設A具有足夠的空間(A陣列的大小大於或等於m+n)去新增B中的元素。 樣例:給出 A = [1, 2, 3, empty, empty], B = [4, 5] 合併之後 A 將

合併K個有序連結串列(採用治法、vector排序法分別實現)

一、合併K個連結串列 將n個已經有序的連結串列,合併成一個連結串列,使之有序 【1】排序法實現,時間複雜度為O(KNlogKN) 【2】分治法實現,時間複雜度為O(KNlogK) #include<iostream > #include&

快速排序(而治之策略C語言實現)

提出的問題 分而治之的策略 重要的分而治之演算法 快速排序 問題 要在一個長為x,寬為y的長方形中畫出均勻且大小相等的正方形 那麼正方形的邊長為多少 (1)可以看出正方形的邊長需要是x和y的最大公約數 如何求最大公約數?