C语言 全排列(包含错误代码及分析,memset简单介绍及举例)

正确代码:

#include <stdio.h>
#include <math.h>
#include <string.h>

int n;//表示位数
int a[10];
int hash_tabel[10];

void print()
{
    for(int i=n;i>0;i--)
        printf("%d",a[i]);
    printf("\n");
}
void core(int d)
{
    if(d==0)//排序完成
    {
        print();
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!hash_tabel[i])
        {
            a[d]=i;
            hash_tabel[i]=1;
            core(d-1);
            hash_tabel[i]=0;
        }
    }
}

int main()
{
    int num;
    scanf("%d",&n);
    core(n);
    return 0;
}

题目来源:

河北大学数据结构与算法第四版教科书P21 题目2。

代码分析:

没有用书上的方法,交换啥的,没想明白,这个代码的基本方法是置入。

基本思路是递归,从1到n依次尝试填入目标位置,在解决当前位置后继续解决下一位置,直到最后一个位置也填好数据,即解决了一种情况,注意在子问题解决后要将 hash_tabel[i]置零还原。

错误代码:

#include <stdio.h>
#include <math.h>
#include <string.h>

int n;//表示位数
int a[10];
int hash_tabel[10];

void init_hash()
{
    memset(hash_tabel,0,sizeof(hash_tabel) );
}

void print()
{
    for(int i=n;i>0;i--)
        printf("%d",a[i]);
    printf("\n");
}

void core(int d)
{
    if(d==0)//排序完成
    {
        print();
        init_hash();//错误点1
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!hash_tabel[i])
        {
            a[d]=i;
            hash_tabel[i]=1;
            core(d-1);
            //错误点2
        }
    }
}

int main()
{
    int num;
    scanf("%d",&n);
    core(n);
    return 0;
}

错误代码分析:

这个是我一开始写出来的代码,主要问题是在解决子问题后没有还原散列,先上错误运行结果:

可以看出一个数值多次出现,一开始我还以为是散列的问题,没有正确初始化,修改了之后还是有问题,后来才想到是子问题解决后没有正确进入下一状态,看如下运行模拟:

输入值 3

进入core函数 当前位置 3 状态1
i=1 a[3]=1 hash[1]=1 递归调用core

进入core函数 当前位置 2 状态2
i=1 无法置入(hash[1]=1)
i=2  a[2]=2 hash[2]=1 递归调用core

进入core函数 当前位置 1 状态3
i=1 无法置入
i=2 无法置入
i=3  a[1]=3 hash[3]=1 递归调用core

进入core函数 当前位置 0 状态4
重置hash为0 退出core 打印 1 2 3

此时回退到 状态3
i=4 退出core

回退到 状态2
i=3 a[2]=3 hash[3]=1 递归调用core

进入core函数 当前位置 1 状态5
i=1  a[1]=1 hash[1]=1 递归调用core

进入core函数 当前位置 0 状态6
重置hash为0 退出core 打印 1 3 1

可以看出问题出在hash的处理上,在最后输出时初始化hash导致在某一状态的子问题解决后处理下一状态时hash是完全错的,正确处理方式应该是当回退到某一状态后同时将hash状态也回退,即正确代码第29行。

另memset用法简记:

头文件:
#include <string.h>
用途:
将数组存储位置以字节为单位进行赋值
函数原型:
void*memset(void* dest ,int c ,size_t count );
参数:
Parameters
dest
Pointer to destination
c
Character to set
count
Number of characters
用法:

我比较常用的是将int数组内容置0,也可以直接置-1,下面举例:

int hash_tabel[10];
memset(hash_tabel,0,sizeof(hash_tabel) );        //写法1
memset(hash_tabel,0,sizeof(hash_tabel[0])*10 );  //写法2
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值