歸併排序(遞迴與非遞迴)的實現
摘要:
(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 *