算法导论(Introduction to Algorithms)之算法入门(插入排序与合并排序C语言实现)

C语言实现:插入排序与合并排序算法解析
本文介绍了算法导论中的插入排序和合并排序。插入排序的时间复杂度为O(n^2),而合并排序的时间复杂度为O(n log n),在处理大量数据时更为高效。文中提供了算法的伪代码和C语言实现,并指出在合并排序中通过额外空间避免了不必要的判断,提升了效率。读者可以下载源码进行学习和实践。

源码下载地址:http://download.csdn.net/detail/mr_dodo/4938878


插入排序:

其算法时间复杂度为C1*n2,C1为一个与n无关的系数,即其算法时间复杂度与n的平方成正比。

其算法伪代码如下:

/*
* INSERTION-SORT(A)
* 
* for j <-- 2 to length[A]
*	do key <-- A[j];
*	   >>insert A[j] into the sorted sequence A[1...j-1]
*	   i <-- j - 1
*	   while i > 0 and A[i] > key
*	      do A[i+1] <-- A[i]
*		     i <-- i - 1;
*	   A[i+1] <-- key;
*
*/

其算法用C语言表示,形式如下:

void InsertionSort(int* arraySort,int arrayLen)
{
	int i = 0,j = 0;

	for (j = 1 ; j <= arrayLen - 1 ; j++)
	{
		int key = arraySort[j];
		i = j - 1;
		while (i >= 0 && arraySort[i] > key)
		{
			arraySort[i+1] = arraySort[i];
			i--;
		}
		arraySort[i+1] = key;
	}
}

其算法分析略之,其算法最好情况所消耗时间为 an+b,其最坏情况为 an2+bn+c,其中a、b、c均为系数。


合并排序:

其算法时间复杂度为C2*nLgn,其中Lg为以2为底的对数函数,C2为一个与n无关的常量,与插入排序相比,Lgn比之n在数量级大的数组(比如一百万、一亿个数的数组)来说,具有更高的效率。

其算法直观操作如下:

分解:将n个元素分成各含n/2个元素的子序列

解决:用合并排序法对两个子序列递归地排序

合并:合并两个已排序的子序列以得到排序结果

在对子序列排序时,其长度为1时递归结束。单个元素被视为是已排好序的。

其算法伪代码如下:

/*
*	MERGE(A,p,q,r)
*	
*	n1 <-- q-p+1
*	n2 <-- r-q
*	>>create arrays L[1...n1+1] and R[1...n2+1]
*	for i <-- 1 to n1
*		do L[i] <-- A[p+i-1]
*	for j <-- 1 to n2
*		do R[j] <-- A[q+j]
*
*	L[n1+1] <-- ∞
*	R[n2+1] <-- ∞
*	i <-- 1
*	j <-- 1
*
*	for k <-- p to r
*		do if L[i] <= R[j]
*			then A[k] <-- L[i]
*				i <-- i+1
*			else A[k] <-- R[j]
*				j <-- j+1
*/


其算法C语言版本如下:


void Merge(int * arrayMerge,int p,int q,int r)
{
	int n1 = q - p + 1;
	int n2 = r - q;

	//Create arrays L[1...n1+1] and R[1...n2+1]
	int* leftArray = (int *)malloc(sizeof(int)*n1);
	int* rightArray = (int *)malloc(sizeof(int)*n2);
	int i = 0;
	int j = 0;
	int k = 0;
	
	for (i = 0;i < n1 ; i++)
	{
		leftArray[i] = arrayMerge[p+i];
	}
	for (j = 0;j < n2 ; j++)
	{
		rightArray[j] = arrayMerge[q+j+1];
	}

	i = 0;
	j = 0;

	for (k = p;k<=r;k++)
	{
		if (i < n1 && j < n2)
		{
			if (leftArray[i] <= rightArray[j])
			{
				arrayMerge[k] = leftArray[i];
				i++;
			}
			else if(j < n2)
			{
				arrayMerge[k] = rightArray[j];
				j++;
			}
		}
		else if (i < n1)
		{
			arrayMerge[k] = leftArray[i];
			i++;
		}
		else if (j < n2)
		{
			arrayMerge[k] = rightArray[j];
			j++;
		}
	}

	free(leftArray);
	leftArray = NULL;
	free(rightArray);
	rightArray = NULL;
}

void MergeSort(int* arraySort,int p,int r)
{
	if (p < r)
	{
		int q = (p + r) / 2;
		MergeSort(arraySort,p,q);
		MergeSort(arraySort,q+1,r);
		Merge(arraySort,p,q,r);
	}
}

上述Merge函数对i、j的值进行了判断,如若按书中伪代码实现,如下:

void Merge(int * arrayMerge,int p,int q,int r)
{
	int n1 = q - p + 1;
	int n2 = r - q;

	//Create arrays L[1...n1+1] and R[1...n2+1]
 	int* leftArray = (int *)malloc(sizeof(int)*(n1+1));
 	int* rightArray = (int *)malloc(sizeof(int)*(n2+1));

	int i = 0;
	int j = 0;
	int k = 0;
	
	for (i = 0;i < n1 ; i++)
	{
		leftArray[i] = arrayMerge[p+i];
	}
	for (j = 0;j < n2 ; j++)
	{
		rightArray[j] = arrayMerge[q+j+1];
	}

	i = 0;
	j = 0;

	leftArray[n1] = INT_MAX;
	rightArray[n2] = INT_MAX;

	for (k = p;k<=r;k++)
	{
		if (leftArray[i] <= rightArray[j])
		{
			arrayMerge[k] = leftArray[i];
			i++;
		}
		else
		{
			arrayMerge[k] = rightArray[j];
			j++;
		}
	}

	free(leftArray);
	leftArray = NULL;
	free(rightArray);
	rightArray = NULL;
}

可以看出,书中的思想,多分配了一个空间存储无穷大的数值,少了许多判断,合并排序效率的确比较高效。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值