|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 Suud 于 2023-5-10 01:10 编辑
题目的要求是:
输入一个正整数n,按照字典序输出从1到n的所有正整数的全排列
比如输入3,输出结果应为:
123
132
213
231
312
321
我写的代码是这样的:
- #include <stdio.h>
- void fp(int a[], int s, int e);
- void change(int a[], int i, int j);
- void sort(int a[], int m, int n);
- int main()
- {
- int i, n;
- printf("输入: ");
- scanf("%d", &n);
- int a[n];
- for (i = 0; i < n; i++)
- a[i] = i + 1;
- fp(a, 0, n);
- return 0;
- }
- void fp(int a[], int s, int n)
- {
- int i, j;
- if (s == n - 1)
- {
- for (i = 0; i < n; i++)
- printf("%d", a[i]);
- putchar('\n');
- }
- else
- for (i = s; i < n; i++)
- {
- change(a, s, i);
- sort(a, s + 1, n);
- fp(a, s + 1, n);
- change(a, i, s);
- }
- }
- void change(int a[], int i, int j)
- {
- int temp = a[i];
- a[i] = a[j];
- a[j] = temp;
- }
- void sort(int a[], int m, int n)
- {
- int i, j, temp;
- for (i = m; i < n; i++)
- {
- for (j = m; j < n - i; j++)
- if (a[j] > a[j + 1])
- {
- temp = a[j];
- a[j] = a[j + 1];
- a[j + 1] = temp;
- }
- }
- }
复制代码
但是当我输入为4或者更大的数字的时候,就会出现错误
比如输入4的结果是这样的:
- 1234
- 1243
- 1324
- 1342
- 1432
- 1423
- 2134
- 2143
- 2314
- 2341
- 2431
- 2413
- 3124
- 3142
- 3214
- 3241
- 3421
- 3412
- 4123
- 4132
- 4213
- 4231
- 4321
- 4312
复制代码
1423和1432的顺序错了,包括下面的2413和2431,3412和3421,4312和4321的顺序也反了
包括输入更大的数字的时候也会出现这样的错误
我感觉是sort函数出了问题,但是又不知道具体是为什么
本帖最后由 sfqxx 于 2023-5-9 21:22 编辑
在你提供的代码中,sort函数实现使用的是冒泡排序(bubble sort)算法。冒泡排序的思想是不断比较相邻的元素,如果顺序不对就交换位置,这样每轮可以确定一个最大的元素,直到所有元素有序为止。
但是在你的代码中,sort函数实现存在两个问题:
1.循环的范围错误
在第二层循环中,j的取值应该从m到n-i-1,而不是从 m 到 n-i。因为每轮都已经将未排序区间中的最大值排在了已排序区间的末尾,所以未排序区间的长度可以减少1。
2.相邻元素对比次数过多
在内层循环中,j的取值始终从m开始,但是已经将前 m-1 个元素排好序了,这些元素不需要再次比较。对于一个长为n的数组,冒泡排序最多进行n^2次对比操作,效率较低。因此我们可以优化这部分代码,在每一轮循环中记录是否发生了交换操作,如果没有交换,则说明已经有序,可以提前结束排序。
优化后的代码如下:
```c
void sort(int a[], int m, int n)
{
int i, j, temp;
for (i = m; i < n - 1; i++)
{
int swapped = 0; // 是否发生交换
for (j = m; j < n - i - 1; j++)
if (a[j] > a[j + 1])
{
swap(a, j, j + 1);
swapped = 1;
}
if (!swapped) break; // 如果没有交换,提前退出循环
}
}
```
通过修改sort函数之后,你的代码可以正确地输出1~4的全排列,且在输入较大的数字时也能得到正确结果。
然而,为了更好地理解问题,我们可以举一个例子来强化理解。以输入为4的情况为例,当程序执行到第一个12xx时,在sort函数中,由于j只取到了i+1,即2,因此在这个子序列中,3和4之间的大小关系并未被考虑到。而在后续遍历的过程中,由于后面每一个位置都可以与2交换,因此出现了2413这样的情况。
经过优化后的sort函数可以避免上述问题,并能够正确输出所有的全排列。
|
|