上一篇数组换位问题的博客,是网上搜的,自己虽然过了一遍,但是还是理解起来有困难。上次上机课,老师给我们提示了另一新颖的解法,自己下来实现了,发此博客记录一下。
算法一:三次反转算法
主要思想:设a[0, k-1]位U,a[k, n-1]为V,换位算法要求将UV变为VU。三次反转先将U反转为U¯¹,再将V反转为V¯¹,最后将U¯¹V¯¹反转为VU。
例如:1 2 3 4 5 6 7 阶段为位置k=2,所以,左边互换为2 1,右边互换为7 6 5 4 3,最后整体互换为3 4 5 6 7 1 2.
代码如下:
#include <stdio.h>
void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void reverse(int a[], int i, int j) {
while(i < j) {
swap(&a[i], &a[j]);
i++;
j--;
}
}
void move(int a[], int n, int k) {
reverse(a, 0, k-1);
reverse(a, k, n-1);
reverse(a, 0, n-1);
}
int main() {
int i;
int k;
int n;
scanf("%d", &n); //输入数组长度
int a[n];
for(i = 0; i < n; i++) {
scanf("%d", &a[i]); //输入数组元素
}
scanf("%d", &k); //输入截断位置
move(a, n, k);
printf("\n");
for(i = 0; i < n; i++) {
printf("%d ", a[i]);
}
return 0;
}
算法二:循环换位算法(平移法)
主要思想:如果k左边的元素个数少于右边的元素个数,则向前循环换位。否则,向后循环换位。
代码如下:
#include <stdio.h>
int temp;
//向前循环换位
void forward(int a[], int n, int k) {
int i, j;
for(i = 0; i < k; i++) {
temp = a[0];
for(j = 1; j < n; j++) {
a[j-1] = a[j];
}
a[n-1] = temp;
}
}
//向后循环换位
void backward(int a[], int n, int k) {
int i, j;
for(i = k; i < n; i++) {
temp = a[n-1];
for(j = n-1; j > 0; j--) {
a[j] = a[j-1];
}
a[0] = temp;
}
}
//选择移动较少的数组块进行循环
void move(int a[], int n, int k) {
if(k > n-k) backward(a, n, k);
else forward(a, n, k);
}
int main() {
int i, n, k;
scanf("%d", &n); //输入数组长度
int a[n];
for(i = 0; i < n; i++) {
scanf("%d", &a[i]); //输入数组元素
}
scanf("%d", &k); //输入截断位置
move(a, n, k);
printf("\n");
for(i = 0; i < n; i++) {
printf("%d ", a[i]);
}
return 0;
}
在最坏的情况下,算法所需的元素移动次数为min{k, n-k}×(n+1)。算法进用到一个辅助空间temp。