1. 程式人生 > >歸併排序(非遞迴) ----- C語言

歸併排序(非遞迴) ----- C語言

歸併排序(Merge sort,臺灣譯作:合併排序)是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。

演算法步驟:

1. 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列

2. 設定兩個指標,最初位置分別為兩個已經排序序列的起始位置

3. 比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置

4. 重複步驟3直到某一指標達到序列尾

5. 將另一序列剩下的所有元素直接複製到合併序列尾


以上理論歸理論,程式碼要實現其實還是有難度的,自己搞了很久才基本弄清楚非遞迴的歸併排序的基本思想,查閱許久才看懂程式碼,自己簡單地實現了一下:

#define A_LENGTH 10
#include <stdio.h>
#include <stdlib.h>

int MergeSort(int *a)
{
	int k = 1;/*k用來表示每次k個元素歸併*/
	int *temp = (int *)malloc(sizeof(int) * A_LENGTH);
	
	while (k < A_LENGTH)
	{
		//k每次乘以2是遵循1->2->4->8->16的二路歸併元素個數的原則
		MergePass(a, temp, k, A_LENGTH);/*先借助輔助空間歸併*/
		k *= 2;
		
		MergePass(temp, a, k, A_LENGTH);/*再從輔助空間將排過序的序列歸併回原陣列*/
		k *= 2;
	}
}


int MergePass(int *S, int *T, int times, int length)
{
	int i = 0, s = times, l;
	
	while ((i + 2*s - 1) < length)
	{
		Merge(S, T, i, i+s-1, i+2*s-1);
		i += 2*s;
	}/*此處的迴圈用於遍歷陣列全部元素並依照k(此處為賦值為s)來歸併入輔助的陣列空間中*/
	
	/*if-else用於處理歸併剩下的序列,因為已經不滿足(i + 2*s - 1) < length的條件
	* 所以需要修改Merge()函式的下標,而如果滿足(i + s - 1) < length即表示
	* i 到 i + s - 1 這段序列為歸併的第一段,剩下一段為 i + s 到 length - 1,
	* 而如果不滿足if條件則說明剩下序列已經有序,直接迴圈賦值給目標陣列即可
	*/
	if ((i + s - 1) < length)
	{
		Merge(S, T, i, i+s-1, length-1);
	}
	else
	{
		for (l = i; l < length; l++)
		{
			T[l] = S[l];
		}
	}
}


//歸併排序最主要實現函式
int Merge(int *S, int *T, int low, int m, int high)
{//j在[m+1,high]區間遞增,k用於目標T的下標遞增, l是輔助變數
	int j, k, l;
	
	for (k = low, j = m+1;
		low <= m  &&  j <= high;
		k++)
	{
		if (S[low] < S[j])
		{
			T[k] = S[low++];	//此處先執行T[k] = S[low],然後low++;
		}
		else
		{
			T[k] = S[j++];		//同理
		}
	}
	
	//for迴圈過後,必然有low>m 或者 j>high,故分情況處理
	if (low <= m)
	{
		for (l = 0; l <= m-low; l++)
		{
			T[k+l] = S[low+l];
		}
	}
	
	if (j <= high)
	{
		for (l = 0; l <= high-j; l++)
		{
			T[k+l] = S[j+l];
		}
	}
}


int main()
{
	int i;
	int a[A_LENGTH] = {50, 90, 80, 40, 30,
						120, 150, 200, 70, 60};
			
	printf("Before sorting:");
	for (i = 0; i < A_LENGTH; i++)
	{
		printf("%d -- ", a[i]);
	}
	
	MergeSort(a);
	
	printf("\n\nAfter sorting: ");
	for (i = 0; i < A_LENGTH; i++)
	{
		printf("%d -- ", a[i]);
	}
	return 0;
}




相關推薦

歸併排序() ----- C語言

歸併排序(Merge sort,臺灣譯作:合併排序)是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。 演算法步驟:

歸併排序實現Java

遞迴實現的歸併排序,需要O(lgN)的棧空間,而非遞迴實現的歸併排序則不需要 原文地址:http://www.jianshu.com/p/39dd1d9b491d public class Sort { public static void MergeSort

歸併排序演算法

#include<cstdio> #include<cstdlib> #define MAX 1000 typedef struct seeqlist { int Array[MAX]; int length; }SeqList; void Merge(int S[],int

歸併排序演算法最通俗易懂的解析

分析: 非遞迴,即迭代,與遞迴最大的區別在於實現的方向不同。遞迴拆開來是“遞推”與“迴歸”,也就是先從頂層往下,逐層遞推到底層,再從底層逐層迴歸到頂層,所以mergesort的遞迴版本是先從頂層開始往下不斷對陣列一分為二,到底層歸併,回到上一層,再歸併,重複直到頂層。非遞迴

二叉樹的遍歷(前序中序後序C語言

前兩天做資料結構實驗,要求用非遞迴演算法遍歷二叉樹。只知道用棧來儲存資料,具體演算法還不太清楚。經過兩天的搜尋,看到網上很多種解法,很多解法都是用C++來寫的演算法,一直找不到用C語言寫的演算法,所以就總結了一下,用C寫出了一個遍歷二叉樹的三種非遞迴演算法。 前

歸併排序形式與形式(C++版)

歸併排序的核心思想是分治法,即將待排序資料分成多個小塊,對每個小塊進行排序,然後在兩兩合併小塊,最終完成對整體的排序 時間複雜度是nlogn 輸入:25,12,17,21,15,48 結果: 遞迴實現:遞迴類似於對此方法的場景再現,即先對整體進行劃分,然後對劃分後的部分

歸併排序實現(C語言

前言:理論很枯燥、文字更煩人,但是這裡將理論知識告訴大家並不是讓大家一上來就看乾巴巴的文字,因為我在程式碼中能註釋的地方都進行了註釋希望大家先跟著註釋打一遍,不要著急,當在黑色的星空中出現了結果,你就會為之振奮,有了繼續學下去的勇氣,當你對程式碼中的思想有了較深的理解後,再回

c 和 Python 實現歸併排序

C: #include <iostream>   using namespace std;   #define MAXSIZE 9 typedef struct {     int r[MAXSIZE+1];     int length; }SqList;

資料結構與演算法 C 歸併(Merge)排序()

7-18 排序(25 分) 給定N個(長整型範圍內的)整數,要求輸出從小到大排序後的結果。 本題旨在測試各種不同的排序演算法在各種資料情況下的表現。各組測試資料特點如下: 資料1:只有1個元素; 資料2:11個不相同的整數,測試基本正確性; 資料3:103個隨機整數

歸併排序的寫法

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

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

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

歸併排序)的實現

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

歸併排序方法實現)

/* 歸併排序 VS2010 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define OK 1 #define ERROR 0 #define MAX

排序歸併排序版本)

#include<iostream> using namespace std; void merge(int* a, int* temp, int begin, int middle, int end){ int i = begin; int j = mi

演算法導論 之 平衡二叉樹 - 建立 插入 查詢 銷燬 - C語言

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

演算法導論 之 平衡二叉樹 - 刪除 - C語言

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

歸併排序理解

https://zh.wikipedia.org/wiki/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F 先上一個網站,這個網站一定要看。 點開之後可以看到歸併排序的動態演示圖,只要能理解這個圖,就能夠理解遞迴和歸併排序了。 你可以看到圖裡面的數分了四層,然後

Java實現--歸併排序

《Java資料結構和演算法》如此描述分治演算法: 把一個大問題分成兩個相對來說更小的問題,並且分別解決每一個小問題,對每一個小問題的解決方案是一樣的:把每個小問題分成兩個更小的問題,並且解決它們。這個過程一直持續小去知道達到易於求解的基值情況,就不用再繼續分了。 時間複雜度:

歸併排序演算法 及迴圈實現

第一步合併相鄰長度為1的子陣列段,這是因為長度為1的子陣列段是已經排好序的。 用一次對陣列arr的線性掃描就足以找出所有這些排好序的子陣列段。然後將相鄰的排好序的子陣列段兩兩合併,構成更大的排好序的子

排序算法系列:歸併排序(Merge sort)(C語言

通俗理解:運用分而治之的思想,編寫遞迴函式,將大陣列排序轉化為小陣列排序,最後再將其合併。void merge_sort(int*p,int low,int high) { int mid = (low+high)/2; if (low <high) { m