1. 程式人生 > >歸併排序(遞迴與非遞迴)的實現

歸併排序(遞迴與非遞迴)的實現

摘要:
(1)歸併排序幾乎以O(NlogN)的時間界實現,是典型的分治演算法;
(2)歸併排序的基本思路很簡單:就是將目標序列分為兩個部分,將兩個子序列排序好之後,再將它們合併。注意到合併兩個已排序的序列只需要O(N)的時間界。
(3)對兩個子序列的排序顯然也是通過遞迴的歸併排序實現的。
(4)需要注意的一個小細節是,當子序列的元素很少時,繼續呼叫歸併排序未必是一件划算的事.因此可以設定一個邊界,當元素個數少於這個值時就掉用最簡單的插入排序.
【1】合併的過程
合併的過程相對簡單,用兩個指標指向兩個子序列的開始點,然後比較它們的大小.將較小的一個放入新的陣列.然後將指向較小元素的指標前移一位。繼續這個過程直到某一個指標達到邊界.然後將另一個子序列的剩餘所有元素都置入新的陣列.
【2】注意的細節:如果每一次遞迴都建立一個新的陣列那麼將會佔用很多的空間.因此合理的做法是在進入遞迴之前建立兩個陣列,然後用兩個變數Left,Right標誌子序列的邊界。每一次合併的過程都是把A[Left1]到A[Right1],A[Left1+1]到A[Right2]合併到B[left1]到B[Right2];

#include "stdafx.h"
#include "malloc.h"
#include "stdlib.h"
#include "string.h"
#define Max 10000000
int Min(int a ,int b)
{
    return a < b ? a:b;
}
void Merge(int *A,int *tmp,int Left1,int Right1,int Left2, int Right2)
{
    if(Left1==Right1&&Right1==Left2&&Left2==Right2)//只有一個元素不用合併
    return
; int point1 = Left1,point2 = Left2,k = Left1; //int tmp[9]; while(point1 <= Right1 && point2 <= Right2) { if(A[point1] <= A[point2]) tmp[Left1++] = A[point1++]; else tmp[Left1++] = A[point2++]; } while(point1 <= Right1) tmp[Left1 ++] = A[point1++]; while
(point2 <= Right2) tmp[Left1++] = A[point2++]; for (Left1 = k;Left1<= Right2;Left1++) { A[Left1] = tmp[Left1]; } }

【2】真正的排序

void Mergesort(int *A,int *tmp,int Left,int Right)
{
    int Center;
    if(Left == Right)//只有一個元素
        return;
    Center = (Left + Right)/2;
    Mergesort(A,tmp,Left,Center);
    Mergesort(A,tmp,Center + 1,Right);
    //下面合併
    Merge(A,tmp,Left,Center,Center+1,Right);
}

【3】以上的程式都是用遞迴的辦法實現。下面用非遞迴的辦法實現歸併排序.
非遞迴的基本思路
(1)我們應該每次對2^i長度的子序列進行合併。例如最開始對長度為1的相鄰子序列進行合併;然後對長度為2的相鄰的子序列進行合併。程式碼如下

void Mergesort2(int *A,int *tmp,int N)
{
    //非遞迴歸併
    int test[9];

    int number = 1;//每次合併個數
    int i,Center,end;
    while(number <= N-1)
    {
    for( i = 0;   i + number<= N ; i += number)
    {
        end = i + number - 1;
        Center = (i + end)/2;
        Merge(A,tmp,i,Center,Center+1,end);

    }
    if (i <= N-1)
    {
        //合併多出的元素
            Merge(A,tmp,i-number,i-1,i,N-1);
    }
    number *= 2;
    }
}
void Msort(int A[],int N)
{
    int i = 1,cutoff,j;
    while(i <= N)
    {
        i *= 2;
    }
    cutoff = i - N;
    int *B = (int *)malloc(sizeof(int)*i);
    int *tmp = (int *)malloc(sizeof(A)*N);
    Mergesort2(A,tmp,N);
    free(tmp);
}

相關推薦

Java排序演算法(三)--歸併排序MergeSort實現

歸併有遞迴和非遞迴兩種。 歸併的思想是: 1.將原陣列首先進行兩個元素為一組的排序,然後合併為四個一組,八個一組,直至合併整個陣列; 2.合併兩個子陣列的時候,需要藉助一個臨時陣列,用來存放當前的

歸併排序實現

摘要: (1)歸併排序幾乎以O(NlogN)的時間界實現,是典型的分治演算法; (2)歸併排序的基本思路很簡單:就是將目標序列分為兩個部分,將兩個子序列排序好之後,再將它們合併。注意到合併兩個已排序

歸併排序的寫法

歸併排序              歸併排序就是把兩組有序的陣列,合併成一個有序的陣列。至於如何分成兩個有序的陣列,遞迴的方法就是,把一個未排序的陣列,一直對半分,直到分成兩個陣列長度為1,然後一層一層合併上去。非遞迴的方法就是,在同一個陣列,從合併相鄰兩個長度為1的資料

排序演算法6——圖解歸併排序及其實現

排序演算法1——圖解氣泡排序及其實現(三種方法,基於模板及函式指標) 排序演算法2——圖解簡單選擇排序及其實現 排序演算法3——圖解直接插入排序以及折半(二分)插入排序及其實現 排序演算法4——圖解希爾排序及其實現 排序演算法5——圖解堆排序及其實現 排序演算法6——圖解歸併排序及其遞迴與非

快速排序 的原理及其java實現

快速排序由於排序效率在同為O(N*logN)的幾種排序方法中效率較高,因此經常被採用,再加上快速排序思想----分治法也確實實用,因此很多軟體公司的筆試面試,包括像騰訊,微軟等知名IT公司都喜歡考這個

歸併排序 實現

歸併排序:要將一個數組排序,可以先(遞迴地)將他分成兩半分別排序,然後將結果歸併起來。 時間複雜度 O(NlogN) 空間複雜度 O(N) 自頂向下,通過遞迴實現: package sort

歸併排序實現

void merge(int a[],int b[],int l,int m,int r){//    int *b=new int[r-l+1];    int i,j,k;     i=l;     j=m+1;     k=l;     while(i<=m&&j<=r){

Lintcode 464. 整數排序 II 歸併排序實現 java

public class Solution { public void sortIntegers2(int[] A) { int [] temp = new int[A.length]; mergeSort(A,0

樹的前、中、後序遍歷演算法、層序遍歷

二叉樹層次遍歷 非遞迴 void LevelOrder(Tree* T) { if(T == nullptr) return ; queue<Tree *> myqueue; myqueue.push(T); while(!myqueu

斐波那契

遞迴 long jumpFloor(int number) { if(number <= 0) return 0; else if(number == 1 ) return 1; return jumpFloor(number-1)

斐波那契數列

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 1e2+10; ll a[MAXN]; ll F[MAXN]; ll f(ll n) ///遞迴 { if

n的階乘

#include <bits/stdc++.h> using namespace std; typedef long long ll; ll f(ll n)///遞迴演算法 { if(n==0 || n==1) return 1; else return n * f

後續遍歷--java版

先訪問左右孩子,再訪問根節點。同樣還是採用棧的形式,但是問題是,先訪問左孩子出棧,根節點不能刪除,再訪問右孩子出棧,最後訪問根節點出棧。我們的思路是這樣的: 對於某個節點p:    1)將p壓入棧中,並將p所有的左孩子,全部壓入棧中: while(stk.

二叉樹深度Depth````

二叉樹 (`Depth`)遞迴 深度優先遍歷 DFS 二叉樹的高度(深度)為二叉樹結點層次的最大值,也可以認為在根節點不為 nullptr 的情況下左右子樹的最大高度 + 1; 先序(後序)遍歷求解二叉樹高度(Depth)的遞迴演算法 演算法描述:深度優先遍歷 

楊輝三角的C語言實現

本文用C語言程式碼實現楊輝三角 遞迴演算法依據於f(m,n)=f(m-1,n)+f(m-1,n-1) 其中(m,n)為楊輝三角第m行第n個元素 演算法程式碼如下:   #include <stdio.h> //遞迴函式 int func(int m,in

python快速排序

寫在前面 眾所周知,快速排序相對於選擇排序,插入排序,氣泡排序等初級排序有著天然的優勢。這是因為快排在交換元素的過程中,兩個發生交換的元素,距離較遠。比如插入排序,新的元素要在已經有序的序列中,一次又一次地找到它應該處於的位置,交換的次數遠遠高於快排。但是,使

二叉樹後序遍歷演算法及C語言實現

二叉樹後序遍歷的實現思想是:從根節點出發,依次遍歷各節點的左右子樹,直到當前節點左右子樹遍歷完成後,才訪問該節點元素。 圖 1 二叉樹   如圖 1 中,對此二叉樹進行後序遍歷的操作過程為: 從根節點 1 開始,遍歷該節點的左子樹(以節點 2 為根節點); 遍歷節點 2 的左子樹(以節點 4 為根

二叉樹先序遍歷及C語言實現

二叉樹先序遍歷的實現思想是: 訪問根節點; 訪問當前節點的左子樹; 若當前節點無左子樹,則訪問當前節點的右子樹; 圖 1 二叉樹   以圖  1 為例,採用先序遍歷的思想遍歷該二叉樹的過程為: 訪問該二叉樹的根節點,找到 1; 訪問節點 1 的左子樹,找到節點 2; 訪問節點 2 的左子

二叉樹前,中,後遍歷

#include<stdio.h> #include<stdlib.h> typedef struct node { char data; struct node *lchild,*rchild; }bintnode; typedef struct

二叉樹的前序,中序,後序,層次遍歷方式

以前在學校學過二叉樹的遍歷,工作後基本上沒用到,現在整理下這幾種排序演算法: 1.java的測試方法: package leetcode.TestList; /** * @author zhangyu * @version V1.0 * @ClassName: TreeNode *