目录
1.项目要求
2.定义模块函数
3.各模块函数实现
4.项目源代码
1. 项目要求
1.1 循环移动数组,循环左移一个元素,循环右移一个元素。
1.2 循环左移 k 个元素 ,循环右移 k 个元素。
2. 定义模块函数
2.1 主函数:main()
2.2 打印函数:Print_Array()
2.3 循环左移:Left_Move_Array()
2.4 循环右移:Right_Move_Array()
2.5 逆置法:ReserveArray()
3. 各模块函数实现
3.1 打印函数:Print_Array()
/** 打印函数 */
void Print_Array(int* br, int n)
{
assert(br != nullptr);
for (int i = 0; i < n; ++i)
{
printf("%4d ", br[i]);
if ((i + 1) % 10 == 0) // 10 个元素换行
{
printf("\n");
}
}
printf("\n");
}
3.2 逆置法:ReserveArray()
①. 算法思想: 逆置法,记录数组的起始位置 left ; 记录数组的末尾位置 right ; left 与 right 互换; 将 left 与 right 进行位置更新,left++,right - -。
②. 源程序
/** 交换函数 指针传递 进行交换*/
void Sweap_Int(int* ap, int* bp)
{
assert(ap != nullptr && bp != nullptr);
int tmp = *ap;
*ap = *bp;
*bp = tmp;
}
/** 逆置法 */
void ReserveArray(int* br, int left, int right)
{
assert(br != nullptr);
while (left < right)
{
Sweap_Int(&br[left], &br[right]); // 调用交换函数 进行交换
left++;
right--;
}
}
3.3 循环左移:Left_Move_Array()
①. 循环左移一位:Left_Move_Array()
1)算法思想:数组中的数据元素依次向左移动一位,取出第一个元素,循环左移一位,最后将原数组中第一个元素放入到数组末端。
2)源程序
/** 循环左移一个数据元素 */
void Left_Move_Array(int* br, int n)
{
assert(br != nullptr && n > 1); // 数据元素大于 1 进行左移
int tmp = br[0]; // 取出第一个元素
for (int i = 0; i < n - 1; ++i)
{
br[i] = br[i + 1]; // 循环左移
}
br[n - 1] = tmp; // 将第一个元素放置到数组末端
}
②. 循环左移 k 位:Left_Move_Array_k()
1)算法思想:方法一,调用循环移动一位函数进行移动,此方法算法时间复杂度较高,故采用方法二,通过逆置法进行移动。循环左移 k 个元素,数组前一部分(0 … k - 1)进行逆置,数组后一部分(k … n - 1)进行逆置,最后数组(0 … n - 1)整体逆置。(方法一代码详见项目全部源码,可提供调试,此处不在展示)
2)源程序
/** 方法二:逆置法 循环左移 k 个元素 */
void Left_Move_Array_k(int* br, int n, int k)
{
assert(br != nullptr && n > 1);
ReserveArray(br, 0, k - 1); // 数组前一部分 0 -- (k - 1) 逆置
ReserveArray(br, k, n - 1); // 数组后一部分 k -- (n - 1) 逆置
ReserveArray(br, 0, n - 1); // 数组整体逆置
}
3.4 循环右移:Right_Move_Array()
①. 循环右移一位:Right_Move_Array()
1)算法思想:数组中的数据元素依次向右移动一位,取出最后一个元素,循环右移一位,最后将原数组中最后一个元素放入到数组首元素位置。
2)源程序
/** 循环右移一个数据元素 */
void Right_Move_Array(int* br, int n)
{
assert(br != nullptr && n > 1);
int tmp = br[n - 1]; // 取出最后一个元素
for (int i = n - 1; i > 0; --i)
{
br[i] = br[i - 1]; // 循环右移一个元素
}
br[0] = tmp; // 将最后一个元素放置到数组首元素位置
}
②. 循环右移 k 位:Right_Move_Array_k()
1)算法思想:方法一,调用循环移动一位函数进行移动,此方法算法时间复杂度较高,故采用方法二,通过逆置法进行移动。循环右移 k 个元素,数组前一部分(0 … n - k - 1)进行逆置,数组后一部分(n - k … n - 1)进行逆置,最后数组(0 … n - 1)整体逆置。(方法一代码详见项目全部源码,可提供调试,此处不在展示)
2)源程序
/** 逆置法 循环右移 k 个元素 */
void Right_Move_Array_k(int* br, int n, int k)
{
assert(br != nullptr && n > 1); // 数组前一部分 0 -- (n - k - 1) 逆置
ReserveArray(br, 0, n - k - 1); // 数组后一部分 (n - k) -- (n - 1) 逆置
ReserveArray(br, n - k, n - 1); // 数组整体逆置
ReserveArray(br, 0, n - 1);
}
3.5 主函数
/** 主函数 */
int main()
{
const int n = 10; // 常整型 只可读不可写
int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
printf("循环移动之前:\n");
Print_Array(ar, n); // 调用打印函数 进行输出打印
printf("循环左移一位元素之后:\n");
Left_Move_Array(ar, n); // 调用左移一位函数 进行数组循环左移一位
Print_Array(ar, n);
printf("循环右移一位元素之后:\n");
Right_Move_Array(ar, n); // 调用右移一位函数 进行循环数组右移一位
Print_Array(ar, n);
printf("循环左移 k 位元素之后:\n");
Left_Move_Array_k(ar, n, 6); // 调用左移 k 位函数 进行循环数组左移 6 位
Print_Array(ar, n);
printf("循环右移 k 位元素之后:\n");
Right_Move_Array_k(ar, n, 3); // 调用右移 k 位函数 进行循环数组右移 3 位
Print_Array(ar, n);
return 0;
}
4. 项目源代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
/**
* 要求:
* 循环移动数组
* 循环左移一个元素 循环右移一个元素
* 循环左移 k 个元素 循环右移 k 个元素
* 方法一:调用循环移动一位函数进行移动
* 方法二:逆置法 进行移动(提高算法时间复杂度)
*/
/** 循环左移一个数据元素 */
void Left_Move_Array(int* br, int n)
{
assert(br != nullptr && n > 1); // 数据元素大于 1 进行左移
int tmp = br[0]; // 取出第一个元素
for (int i = 0; i < n - 1; ++i)
{
br[i] = br[i + 1]; // 循环左移
}
br[n - 1] = tmp; // 将第一个元素放置到数组末端
}
/** 循环右移一个数据元素 */
void Right_Move_Array(int* br, int n)
{
assert(br != nullptr && n > 1);
int tmp = br[n - 1]; // 取出最后一个元素
for (int i = n - 1; i > 0; --i)
{
br[i] = br[i - 1]; // 循环右移一个元素
}
br[0] = tmp; // 将最后一个元素放置到数组首元素位置
}
/** 方法一:效率较低
// 循环左移 k 个元素
void Left_Move_Array_k(int* br, int n, int k)
{
assert(br != nullptr && n > 1);
k = k % n; // 循环左移 3 个元素和循环左移 13 个元素相同
if (k >= 0)
{
while (k--) // k 大于 0 左移
{
Left_Move_Array(br, n); // 调用循环左移一位函数 进行循环左移 k 个元素
}
}
else // k 小于 0 右移
{
while (k++)
{
Right_Move_Array(br, n); // 调用循环右移一位函数 进行循环右移 k 个元素
}
}
}
//循环右移 k 个数据元素
void Right_Move_Array_k(int* br, int n, int k)
{
assert(br != nullptr && n > 1);
Left_Move_Array_k(br, n, -k); // 调用循环左移 k 个元素, k 小于 0 右移 ,k 大于 0 左移
}
*/
/** 交换函数 */
void Sweap_Int(int* ap, int* bp)
{
assert(ap != nullptr && bp != nullptr);
int tmp = *ap;
*ap = *bp;
*bp = tmp;
}
/** 逆置法 */
void ReserveArray(int* br, int left, int right)
{
assert(br != nullptr);
while (left < right)
{
Sweap_Int(&br[left], &br[right]); // 调用交换函数 进行交换
left++;
right--;
}
}
/** 方法二:逆置法 循环左移 k 个元素 */
void Left_Move_Array_k(int* br, int n, int k)
{
assert(br != nullptr && n > 1);
ReserveArray(br, 0, k - 1); // 数组前一部分 0 ... (k - 1) 逆置
ReserveArray(br, k, n - 1); // 数组后一部分 k ... (n - 1) 逆置
ReserveArray(br, 0, n - 1); // 数组整体逆置
}
/** 方法二:逆置法 循环右移 k 个元素 */
void Right_Move_Array_k(int* br, int n, int k)
{
assert(br != nullptr && n > 1); // 数组前一部分 0 ... (n - k - 1) 逆置
ReserveArray(br, 0, n - k - 1); // 数组后一部分 (n - k) ... (n - 1) 逆置
ReserveArray(br, n - k, n - 1); // 数组整体逆置
ReserveArray(br, 0, n - 1);
}
/** 打印函数 */
void Print_Array(int* br, int n)
{
assert(br != nullptr);
for (int i = 0; i < n; ++i)
{
printf("%4d ", br[i]);
if ((i + 1) % 10 == 0) // 10 个元素换行
{
printf("\n");
}
}
printf("\n");
}
/** 主函数 */
int main()
{
const int n = 10; // 常整型 只可读不可写
int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
printf("循环移动之前:\n");
Print_Array(ar, n); // 调用打印函数 进行输出打印
printf("循环左移一位元素之后:\n");
Left_Move_Array(ar, n); // 调用左移一位函数 进行数组循环左移一位
Print_Array(ar, n);
printf("循环右移一位元素之后:\n");
Right_Move_Array(ar, n); // 调用右移一位函数 进行循环数组右移一位
Print_Array(ar, n);
printf("循环左移六位元素之后:\n");
Left_Move_Array_k(ar, n, 6); // 调用左移 k 位函数 进行循环数组左移 6 位
Print_Array(ar, n);
printf("循环右移三位元素之后:\n");
Right_Move_Array_k(ar, n, 3); // 调用右移 k 位函数 进行循环数组右移 3 位
Print_Array(ar, n);
return 0;
}