0
点赞
收藏
分享

微信扫一扫

华为 RIP 协议中 RIP 兼容版本、RIPv1、RIPv2 在收发 RIP 报文时的区别

一叶轻舟okok 2024-07-24 阅读 26
算法

概念

基本思想:归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有
序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:

归并排序的递归实现

原理

实现

比较begin1和begin2的值的大小,小的插到tmp数组后面,代码实现如下:

	//归并	
	int begin1 = begin, end1 = mid;
	int begin2 = mid +1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	//只有begin1或begin2其中一个结束了才会进入后面的循环.

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}

了解归并排序的单趟过程后,再对其进行递归,即可实现归并排序,代码如下:

//处理一段区间
void _MergeSort(int* a, int* tmp, int begin, int end)
{
	if (begin = end)	
		return;

	int mid = (begin + end) / 2;
	//将区间分为[begin, mid] [mid + 1, end]两个区间,若两区间都有序即可
	_MergeSort(a, tmp, begin, mid);
	_MergeSort(a, tmp, mid + 1, end);

	//归并	
	int begin1 = begin, end1 = mid;
	int begin2 = mid +1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	//只有begin1或begin2其中一个结束了才会进入后面的循环.

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}

void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail!");
	}
	_MergeSort(a, tmp, 0, n - 1);

	free(tmp);
	tmp = NULL;
}
递归的理解 

假设现在我们排0到9这10个数据,则我们先走左边(begin到mid)0到4,要想让0到4有序,则先走左边(0到2),要想让0到2有序,则继续递归分为0到1,再继续分为0到0,1到1,即左边分完,再继续向上再继续递归右边(3到4),再往上走,类似于二叉树中的后 序遍历. 递归展开图:

时间复杂度

空间复杂度也类似于堆排序,每一层有N个,有logN层,则时间复杂度为O(logN).

归并排序的非递归实现

 对于归并排序的非递归实现,我们需要转换思路,将数据一一归并,再两两归并,再四四归并......依此类推:

非递归的本质其实是循环,我们设一个gap为每组归并数据的个数,如上图,第一排gap为1,第二排为2,第三排为4,依此类推, 首先将数据两两配对,再四四配对,代码实现如下:

void MergeSortNonR(int* a, int n)
{

	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail!");
	}
	//gap为每组归并数据的数据个数
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)//i代表了每次归并的起始位置
		{
			//[begin1, end1] [b	egin2, end2]
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[i++] = a[begin1++];
				}
				else
				{
					tmp[i++] = a[begin2++];
				}
			}
			//只有begin1或begin2其中一个结束了才会进入后面的循环.

			while (begin1 <= end1)
			{
				tmp[i++] = a[begin1++];
			}

			while (begin2 <= end2)
			{
				tmp[i++] = a[begin2++];
			}
			memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));//每次归并后都拷贝回去	
		}
		gap *= 2;	

	}
	//归并一次归两组
	free(tmp);
	tmp = NULL;
}

但如图所示,我们只能排列2的指数次方数的数据,因为不为2的偶数次方数的数据会导致数据溢出,在控制台显示如下: 

一共10个数据,如果显示大于9的数据都是溢出的数据,而数据溢出分为三种情况

第一种与第二种合并为第一种

1.右边数组全部溢出

这种代表右边已经是大数,我们不用管,直接尾插入新数组即可.

if (begin2 >= n)
{
	break;
}

2.右边数组未全部溢出

这种情况我们要对数组进行调整处理(修正):将end2减一即可

if (end2 >= n)
{
	end2 = n - 1;
}

这样,我们的总代码即为:

总代码

void MergeSortNonR(int* a, int n)
{

	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail!");
	}
	//gap为每组归并数据的数据个数
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)//i代表了每次归并的起始位置
		{
			//[begin1, end1] [b	egin2, end2]
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//第二组不存在(都越界),则不需要归并
			int j = i;
			if (begin2 >= n)
			{
				break;
			}
			//第二组的begin2没有越界,则需要修正,并继续归并
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[i++] = a[begin1++];
				}
				else
				{
					tmp[i++] = a[begin2++];
				}
			}
			//只有begin1或begin2其中一个结束了才会进入后面的循环.

			while (begin1 <= end1)
			{
				tmp[i++] = a[begin1++];
			}

			while (begin2 <= end2)
			{
				tmp[i++] = a[begin2++];
			}
			memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));//每次归并后都拷贝回去	
		}
		gap *= 2;	

	}
	//归并一次归两组
	free(tmp);
	tmp = NULL;
}

 

 

举报

相关推荐

HCNP——RIPv1和RIPv2概况

0 条评论