问题描述:内存重叠就是拷贝的目的地址和源地址有重叠。
举一个简单例子:有数组str={1,2,3,4,5,6,7,8,9};
现要求将后三个数移动到最前面
我们需要进行的操作:
1.创建一个临时数组保存要移动的数字(7,8,9);
2.将剩余数字(1~7)向后移动三位;
3.将临时数组中的数据传给空余位置(最前面三位);
我们需要考虑的是:向后移动还是想向前移动?
先移动1?还是先移动7?
当然,此例中要先移动7向后移,那么为什么不先从1开始移动呢?
这是因为
当红色部分存到临时数组中时,若从1移动则出现内存重叠(即蓝色部分),所以4~6会被覆盖掉
通过此例我们需要思考:什么时候从前面移动?什么时候从后面移动?什么时候前后都可以?
总结如下:
1.n个数,将后m个数移动到最前面
①:m<n/2时,从先后面移动;
②:m>n/2时,前后都可以;
③:m=n/2时,前后都可以;
2.n个数,将前m个数移动到最后面
①:m<n/2时,先从前面移动;
②:m>n/2时,前后都可以;
③:m=n/2时,前后都可以;
3.特殊情况(前后移动都可以):当需要移动的部分和剩余部分各为整体一半时
例:
//2.n个整数数字后移m位,最后m个数移到最前面,主函数输入输出n
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void Move(int *arr,int n,int m)
{
assert(arr!=NULL);
int *brr=(int *)malloc((n-m)*sizeof(int));
for(int i=0;i<n-m;i++)//将n-m个数依次复制到brr中
{
brr[i]=arr[i];
}
for(int i=0;i<m;i++)//将m个数依次复制到前m个arr中
{
arr[i]=arr[n-m+i];
}
for(int i=0;i<n-m;i++)//将brr即(n-m)依次复制到m+1后
{
arr[m+1]=brr[i];
}
for(int i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
free(brr);
}
int main()
{
int arr[]={11,22,33,44,55,66,77,88,99};
int n=sizeof(arr)/sizeof(arr[0]);
Move(arr,n,5);
return 0;
}