题目
将数组中的元素(X1,X2,...,Xn-1)经过移动后变为(Xp,Xp+1,...,Xn-1,X0,X1,..,Xp-1),即循环左移p(0<p<n)个位置。设计算法来解决这个问题。
分析
如有数组[1,2,3,4,5,6,7]将其循环左移3个位置后变成[4,5,6,7,1,2,3]
下面是上面图片的代码实现:
#include <stdio.h>
/* 将数组指定个元素逆序 */
/* a[]指的是是要逆置的数组;left指的是起始下标;right指的是结束下标;k指的是要逆置的数组元素个数 */
void reverse(int a[],int left,int right,int k) {
int temp,count=0;// 临时变量,用来临时存储数组中的变量值
// for(int i=left,j=right;i<left+k&&i<j;i++,j--){ // 这是参考书上的写法,感觉理解有些困难
for(int i=left,j=right; count<k/2; i++,j--,count++) { // 这种写法理解起来相对容易些
temp=a[j];
a[j]=a[i];
a[i]=temp;
}
}
void printArray(int a[],int n) {
printf("\n");
for(int i=0; i<n; i++) {
printf("%d\t",a[i]);
}
printf("\n");
}
/* 主函数:测试结果 */
int main() {
/* 创建一个测试数组 */
int a[]= {1,2,3,4,5,6,7};
printArray(a,7);
/* 首先翻转123 */
reverse(a,0,2,3);
printArray(a,7);
/* 接着翻转4567 */
reverse(a,3,6,4);
printArray(a,7);
/* 最后翻转整个数组 */
reverse(a,0,6,7);
printArray(a,7);
return 0;
}
运行效果如下:
总结
给定一个线性表,将其中的元素逆置:设置两个整型变量i和j,i指向第一个元素,j指向最后一个元素,边交换i和j的元素,边让i和j相向而行,直到相遇。核心代码如下:
for(int i=left,j=right; i<j; i++,j--) {
temp=a[j];
a[j]=a[i];
a[i]=temp;
}
不过本题的代码整理总结如下:
#include <stdio.h>
/* 将数组指定个元素逆序 */
/* a[]指的是是要逆置的数组;left指的是起始下标;right指的是结束下标;k指的是要逆置的数组元素个数 */
void reverse(int a[],int left,int right,int k) {
int temp,count=0;// 临时变量,用来临时存储数组中的变量值。其中temp是用来临时保存i或j的,其中count是计数器,记录循环次数
// for(int i=left,j=right;i<left+k&&i<j;i++,j--){ // 这是参考书上的写法,理解有些困难
for(int i=left,j=right; count<k/2; i++,j--,count++) { // 感觉这样写理解容易些,两句效果一样
// 交换a[i]和a[j]的值
temp=a[j];
a[j]=a[i];
a[i]=temp;
}
}
/* 打印数组元素 */
/* a[]指的是要被打印输出的数组;n指的是数组中的元素个数 */
void printArray(int a[],int n) {
printf("\n");
for(int i=0; i<n; i++) {
printf("%d\t",a[i]);
}
printf("\n");
}
/* 主函数:测试结果 */
int main() {
int num,move;// 两个变量,num用来保存用户输入的数组长度,move用来保存用户输入的移动几个位置
printf("请输入数组元素的个数:");
scanf("%d",&num); // 获取用户输入的num
int a[num];
for(int i=0; i<num; i++) { // 循环输入数组元素
scanf("%d",&a[i]);
}
printArray(a,num);// 打印数组
printf("请输入循环左移多少个位置:");
scanf("%d",&move); // 获取用户输入的move
if(move<0||move>=num) { // 判断用户输入的move是否合法
printf("输入的移动位置不合法!");
} else {
reverse(a,0,move-1,move);// 逆置a[0]-a[move-1]
reverse(a,move,num-1,num-move);// 逆置a[move]-a[num-1]
reverse(a,0,num-1,num);// 逆置a[0]-a[num-1]
}
printArray(a,num);// 打印逆置后的数组
return 0;
}
测试效果如下:
我觉得使用while循环更好理解些,代码更加易懂。
#include <stdio.h>
void printArray(int a[],int n) {
printf("\n");
for(int i=0; i<n; i++) {
printf("%d\t",a[i]);
}
printf("\n");
}
/***** 核心代码 0 *****/
// 逆置数组中指定范围内的元素,其中arr指的是是要进行操作的数组,start是开始下标,end是结束下标
void reverse(int arr[],int start, int end)
{
int temp;
while(start<end)
{
temp=arr[start];
arr[start]=arr[end];
arr[end]=temp;
start++;
end--;
}
}
/***** 核心代码 1 *****/
int main()
{
// 循环左移k个位置
int arr[]={1, 2, 3, 4, 5, 6, 7};
int length=7;
int k=1;
printArray(arr,length);
/***** 核心代码 0 *****/
reverse(arr,0,k-1);
reverse(arr,k,length-1);
reverse(arr,0,length-1);
/***** 核心代码 1 *****/
printArray(arr,length);
return 0;
}