一步一步写算法(之合并排序)

原文:一步一步写算法(之合并排序)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

    前面一篇博客提到的快速排序是排序算法中的一种经典算法。和快速排序一样,合并排序是另外一种经常使用的排序算法。那么合并排序算法有什么不同呢?关键之处就体现在这个合并上面。
    合并算法的基本步骤如下所示:
    1)把0~length-1的数组分成左数组和右数组
    2)对左数组和右数组进行迭代排序
    3)将左数组和右数组进行合并,那么生成的整个数组就是有序的数据数组

    下面就开始实践操作:
    a)创建函数,判断参数的合法性

void merge_sort(int array[], int length)
{
	if(NULL == array || 0 == length)
		return ;
	_merge_sort(array, 0, length-1);
}

    b)进行merge函数迭代操作

void _merge_sort(int array[], int start, int end)
{
	if(start >= end)
		return;

	int middle = start + ((end - start) >> 1);
	_merge_sort(array, start, middle);
	_merge_sort(array, middle + 1, end);
	_merge_data_in_array(array, start, middle, end);
}

    c)对合并后的队列进行合并操作

void _merge_data_in_array(int array[], int start, int middle, int end)
{
	int length = end - start + 1;
	int* pData = NULL;
	int left = start;
	int right = middle + 1;
	int all = 0;

	/* allocate new memory to the space */
	pData = (int*) malloc(sizeof(int) * length);
	assert(NULL != pData);
	memset(pData, 0, length);

	/* begin to move data */
	while(right <= end){
		while(array[left] <= array[right] && left <= middle){
			pData[all] = array[left]; left ++; all ++;
		}

		if(left > middle)  {
			break;
		}

		while(array[left] > array[right] && right <= end){
			pData[all] = array[right]; right ++; all ++;
		}
	}

	/* move the left data */
	if(left <= middle)
		memmove(&pData[all], &array[left], sizeof(int) * (middle -left +1));

	if(right <= end)
		memmove(&pData[all], &array[right], sizeof(int) * (end - right + 1));

	memmove(&array[start], pData, sizeof(int) * length);
	free(pData);
}

    注: 文中使用的pData动态内存不是一种最优的处理办法,实际开发中可以由其他形式的数据类型代替。

    d)编写测试用例

static void test1()
{
	int array[] = {1};
	merge_sort(array, sizeof(array)/sizeof(int));
}

static void test2()
{
	int array[] = {2, 1};
	merge_sort(array, sizeof(array)/sizeof(int));
	assert(1 == array[0]);
	assert(2 == array[1]);
}

static void test3()
{
	int array[] = {3, 2, 1};
	merge_sort(array, sizeof(array)/sizeof(int));
	assert(1 == array[0]);
	assert(2 == array[1]);
	assert(3 == array[2]);
}

static void test4()
{
	int array[] = {4, 3, 5, 1};
	merge_sort(array, sizeof(array)/sizeof(int));
	assert(1 == array[0]);
	assert(3 == array[1]);
	assert(4 == array[2]);
	assert(5 == array[3]);
}

分析快速排序和合并排序的相同点和不同点:
    相同点: 都是迭代操作
    不同点: 快速排序,先分类再迭代;合并排序,先迭代再合并

【预告: 下面一篇博客主要介绍堆排序】

时间: 2025-01-24 13:35:23

一步一步写算法(之合并排序)的相关文章

一步一步写算法(之排序二叉树线索化)

原文:一步一步写算法(之排序二叉树线索化) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作.二叉树插入.二叉树删除1.删除2.删除3.但是排序二叉树也不是没有缺点,比如说,如果我们想在排序二叉树中删除一段数据的节点怎么办呢?按照现在的结构,我们只能一个一个数据查找验证,首先看看在不在排序二叉树中,如果在那么删除:如果没有这个数据,那么继续查找.那么有没有方法

一步一步写算法(之排序二叉树删除-1)

原文:一步一步写算法(之排序二叉树删除-1) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写测试用例不光可以验证我们编写的代码是否正确,还能不断提高我们开发代码的自信心.这样,即使我们在开发过程对代码进行修改或者优化也不会担心害怕.

一步一步写算法(之排序二叉树)

原文:一步一步写算法(之排序二叉树) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点.它是这样定义的: typedef struct _TREE_NODE { int data; struct _TREE_NODE* parent;

一步一步写算法(之排序二叉树的保存和加载)

原文:一步一步写算法(之排序二叉树的保存和加载)[ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     排序二叉树是我们开发中经常使用到的一种数据结构,它具有较好的插入.删除.查找特性.但是由于二叉树的指针较多,所以相比较其他的数据结构而言,二叉树来得比较麻烦些.但是也不是没有办法,下面介绍一下我个人常用的方法.     我们知道,如果一个二叉树是一个满树的话,那么二叉树的节点应该是按照1.2.3.4依次排开的.但是现实情况是这样的,由于

一步一步写算法(之排序二叉树插入)

原文:一步一步写算法(之排序二叉树插入) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     二叉树的节点插入比较简单.一般来说,二叉树的插入主要分为以下两个步骤:     1) 对当前的参数进行判断,因为需要考虑到头结点,所以我们使用了指针的指针作为函数的输入参数     2) 分情况讨论:         如果原来二叉树连根节点都没有,那么这个新插入的数据就是根节点:         如果原来的二叉树有根节点,那我们判断这个数据是

一步一步写算法(之排序二叉树删除-2)

原文:一步一步写算法(之排序二叉树删除-2) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     2.4 删除节点的左右子树都存在,此时又会分成两种情形     1)左节点是当前左子树的最大节点,此时只需要用左节点代替根节点即可 /* * * 10 ======> 6 * / \ / \ * 6 15 5 15 * / * 5 */     代码该怎么编写呢? STATUS delete_node_from_tree(TREE_NOD

一步一步写算法(之排序二叉树删除-3)

原文:一步一步写算法(之排序二叉树删除-3) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     3 普通节点的删除     3.1 删除的节点没有左子树,也没有右子树      测试用例1: 删除节点6 /* * * 10 ======> 10 * / \ \ * 6 15 15 * */ static void test8() { TREE_NODE* pTreeNode = NULL; assert(TRUE == insert

Javascript排序算法之合并排序的2个例子介绍

 这篇文章主要介绍了Javascript排序算法之合并排序(归并排序)的2个例子,需要的朋友可以参考下 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.   归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列.   归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(

Javascript排序算法之合并排序(归并排序)的2个例子_基础知识

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个

一步一步写算法(之 算法总结)

原文:一步一步写算法(之 算法总结) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]       自10月初编写算法系列的博客以来,陆陆续续以来写了几十篇.按照计划,还有三个部分的内容没有介绍,主要是(Dijkstra算法.二叉平衡树.红黑树).这部分会在后面的博客补充完整.这里主要是做一个总结,有兴趣的朋友可以好好看看,欢迎大家提出宝贵意见.       (1) 排序算法     快速排序           合并排序     堆排序