内存重叠问题

关于内存重叠问题,以一个题为例:

有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数。

我们通常会遇到以下四种情况:

(1)如下图,将10个数中后3个数变为最前面3个数,前面各数顺序向后移动3个位置。由图可以看出,我们在移动时,先将后面3个数存到一个临时数组中,然后将剩下的数必须先从7开始依次向后移动3个位置,因为存在内存重叠问题,下图中蓝色部分为内存重叠部分,剩下的数都移动完之后,再将临时数组中存储的最后面3个数依次移动到最前面。



代码如下:

# include<stdio.h>
# include<stdlib.h>
void Move(int *arr,int n,int m)
{
	if(m<=0 || n<=0 || m>=n)
	{
		return ;
	}
	int * brr = (int *)malloc(m*sizeof(int));
	int i;

	for(i=0;i<m;i++)//将后面的数据移到新的内存区域
	{
		brr[i] = arr[n-m+i];
	}

	for(i=n-m-1;i>=0;i--)//数据后移,注意方向
	{
		arr[i+m] = arr[i];
	}
	for(i=0;i<m;i++)
	{
		arr[i] = brr[i];
	}

	free(brr);
}

void Show(int *arr,int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8,9,10};
	Move(arr,10,3);
	Show(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

(2)如下图,将10个数中最前面3个数变为最后面3个数,使后面各数顺序向前移动3个位置。由图可以看出,我们在移动时,先将前面3个数存到一个临时数组中,然后将剩下的数必须先从4开始依次向前移动3个位置,因为存在内存重叠问题,下图中蓝色部分为内存重叠部分,剩下的数都移动完之后,再将临时数组中存储的最前面3个数依次移动到最后面。



代码如下:

# include<stdio.h>
# include<stdlib.h>
void Move(int *arr,int n,int m)
{
	if(m<=0 || n<=0 || m>=n)
	{
		return ;
	}
	int * brr = (int *)malloc(m*sizeof(int));
	int i;
	int j;
	for(i=0;i<m;i++)//将前面的数据移到新的内存区域
	{
		brr[i] = arr[i];
	}

	for(i=m;i<n;i++)//数据前移,注意方向
	{
		arr[i-m] = arr[i];
	}
	for(i=n-m,j=0;i<n,j<m;i++,j++)
	{
		arr[i] = brr[j];
		
	}

	free(brr);
}

void Show(int *arr,int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8,9,10};
	Move(arr,10,3);
	Show(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

(3)如下图,将10个数中后5个数变为最前面5个数,前面各数顺序向后移动5个位置。由图可以看出,我们在移动时,先将后面5个数存到一个临时数组中,然后将剩下的数依次向后移动5个位置,现在这种情况我们可以先移动1,也可以先移动5,因为这种情况不存在内存重叠的问题,剩下的数都移动完之后,再将临时数组中存储的最后面5个数依次移动到最前面。


从5开始移动的代码和(1)中的相同,这里给出从1开始移动。

代码如下:

# include<stdio.h>
# include<stdlib.h>
void Move(int *arr,int n,int m)
{
	if(m<=0 || n<=0 || m>=n)
	{
		return ;
	}
	int * brr = (int *)malloc(m*sizeof(int));
	int i;
	int j;
	for(i=0;i<m;i++)//将后面的数据移到新的内存区域
	{
		brr[i] = arr[n-m+i];
	}

	for(i=0;i<m;i++)//数据后移,注意方向
	{
		arr[i+m] = arr[i];
	}
	for(i=0,j=0;i<n,j<m;i++,j++)
	{
		arr[i] = brr[j];
		
	}

	free(brr);
}

void Show(int *arr,int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8,9,10};
	Move(arr,10,5);
	Show(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

(4)如下图,将10个数中最前面5个数变为最后面5个数,使后面各数顺序向前移动5个位置。由图可以看出,我们在移动时,先将前面5个数存到一个临时数组中,然后将剩下的数依次向后移动5个位置,现在这种情况我们可以先移动6,也可以先移动10,因为这种情况不存在内存重叠的问题,剩下的数都移动完之后,再将临时数组中存储的最前面5个数依次移动到最后面。


同样从6开始移动的代码和(2)的代码相同,这里给出从10开始移动的代码。

代码如下:

# include<stdio.h>
# include<stdlib.h>
void Move(int *arr,int n,int m)
{
	if(m<=0 || n<=0 || m>=n)
	{
		return ;
	}
	int * brr = (int *)malloc(m*sizeof(int));
	int i;
	int j;
	for(i=0;i<m;i++)//将前面的数据移到新的内存区域
	{
		brr[i] = arr[i];
	}

	for(i=n-m;i<n;i++)//数据前移,注意方向
	{
		arr[i-m] = arr[i];
	}
	for(i=n-m,j=0;i<n,j<m;i++,j++)
	{
		arr[i] = brr[j];
		
	}

	free(brr);
}

void Show(int *arr,int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8,9,10};
	Move(arr,10,5);
	Show(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值