C语言怎么实现有重复元素的全排列?

作者&投稿:邲巩 (若有异议请与网页底部的电邮联系)
C语言如何实现有重复元素的全排列?~

在递归里面用交换的方式获取全排列,从第一个开始,不断与后面数交换,当然递归时不要忘记在后面写个换回来的语句。只要加个交换条件就可以了,在不相等时交换,相等时不交换。
当前阶段,在编程领域中,C语言的运用非常之多,它兼顾了高级语言和汇编语言的优点,相较于其它编程语言具有较大优势。计算机系统设计以及应用程序编写是C语言应用的两大领域。同时,C语言的普适较强,在许多计算机操作系统中都能够得到适用,且效率显著。
C语言拥有经过了漫长发展历史的完整的理论体系,在编程语言中具有举足轻重的地位。



特有特点
C语言是普适性最强的一种计算机程序编辑语言,它不仅可以发挥出高级编程语言的功用,还具有汇编语言的优点,因此相对于其它编程语言,它具有自己独特的特点。具体体现为以下三个方面:
其一,广泛性。C语言的运算范围的大小直接决定了其优劣性。C语言中包含了34种运算符,因此运算范围要超出许多其它语言,此外其运算结果的表达形式也十分丰富。此外,C语言包含了字符型、指针型等多种数据结构形式,因此,更为庞大的数据结构运算它也可以应付。
其二,简洁性。9类控制语句和32个关键字是C语言所具有的基础特性,使得其在计算机应用程序编写中具有广泛的适用性,不仅可以适用广大编程人员的操作,提高其工作效率,同时还能够支持高级编程,避免了语言切换的繁琐。
其三,结构完善。C语言是一种结构化语言,它可以通过组建模块单位的形式实现模块化的应用程序,在系统描述方面具有显著优势,同时这一特性也使得它能够适应多种不同的编程要求,且执行效率高。

#include
#include
#include
#define TRUE 1
#define FALSE 0
// 字符串最大长度
#define MAX_STRING_LENGTH 50
// 全排列顺序。TRUE:按字母序升序;FALSE:按字母序降序。
#define PERMUTATION_ASSCENDING_ORDER TRUE
// qsort 函数使用的比较函数
int compare(const void *a, const void *b)
{
return PERMUTATION_ASSCENDING_ORDER
? *((char*)a) - *((char*)b)
: *((char*)b) - *((char*)a);
}
/*
无重复全排序。
参数:
str 要进行无重复全排序的字符串。
字符串内字符必须已经排序过(升序或降序都可以)

isUsed 如果 isUsed[i] = TRUE 表示 str[i] 已经加入当前排列中

p 当前排列中已经存在的字符数

buffer 当前的排列。
buffer[0]~buffer[p-1] 是 str 中已经加入排列的字符。

返回:
无重复全排序的总数。
*/
int Perm(char str[],int isUsed[],int p ,char buffer[])
{
int len=strlen(str),i,j,total=0;

if(p == len)
{// 输出一个全排列
printf("%s
",buffer);
return 1;
}

for(i=0;i<len;i++)
{
if(!isUsed[i])
{
// 查询当前字符的后面,是否已经有和当前字符相同的字母加入了全排序中。
for(j=i+1;j<len;j++)
if(str[i]==str[j] && isUsed[j])
break;

if(j == len)
{ // 当前字符的后面,没有和当前字符相同的字母加入了全排序中。
// 当前字符可以加入全排序

isUsed[i] = TRUE;
buffer[p] = str[i];
total += Perm(str,isUsed,p+1,buffer);
isUsed[i] = FALSE;
}
}
}
return total;
}

int main(int argc, char *argv[])
{
char str[MAX_STRING_LENGTH]="aacc";
char buffer[MAX_STRING_LENGTH]={0};
int isUsed[MAX_STRING_LENGTH]={0};

while(scanf("%s",str)!=EOF)
{
// 先按字母序排序
qsort(str,strlen(str),sizeof(str[0]),compare);
// 全排列
printf("Total %d

",Perm(str,isUsed,0,buffer));
}
return 0;
}

整体思路就是利用回溯的思想,也可认为是深度优先搜索

从字符串第一位idx=0开始,每次递归都从s[idx]之后选择一个字符与s[idx]交换

因为可能有重复字符,可使用哈希数组标记当前循环每个字符是否被选择

因为字符范围不超过ASCII码,所以使用128空间的数组足够用来标记了

选择好当前字符s[i]并与s[idx]交换之后,递归调用继续排列下一位s[idx+1]

注意这里要进行回溯,即不选s[i]而选择之后的某个字符交换到s[idx]

所以要将之前的s[i]与s[idx]交换过来,恢复原状,才能循环判断下一个选择

具体代码截图如下:

运行结果如下:

结果正确,望采纳~

附源码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAXN 1000000 // 排列总数可能很多

int num = 0; // 记录排列总数

char *res[MAXN] = {NULL}; // 指针数组保存排列结果

void swap(char *x, char *y) { // 交换两个字符变量的内容

    char ch = *x;

    *x = *y;

    *y = ch;

}

void perm(char *s, int n, int idx) { // 回溯产生字符串全排列

    if (idx == n) { // 已排列到字符串结尾

        res[num] = (char *)malloc(sizeof(char) * (n + 1));

        //printf("%s
", s); // 输出当前排列

        strcpy(res[num], s); // 保存当前排列

        num++; // 排列总数加1

        return;

    }

    int i, hash[128] = {0}; // 哈希数组,标记每个字符是否被选择

    for (i = idx; i < n; i++) {

        if (hash[s[i]] == 1)

            continue; // 跳过已被标记过的重复字符

        hash[s[i]] = 1; // 选过的话在数组中标记为1

        swap(&s[idx], &s[i]); // 选择s[i]交换到s[idx]

        perm(s, n, idx + 1); // 递归,继续s[idx+1]的选择

        swap(&s[idx], &s[i]); // 回溯,当前不选择s[i],而选择其他字符

    }

}

int main() {

    int n, i;

    scanf("%d", &n);

    char *s = (char *)malloc(sizeof(char) * (n + 1));

    scanf("%s", s);

    perm(s, n, 0);

    printf("一共有%d种排列:
", num); // 输出排列总数

    for (i = 0; i < num; i++) { // 输出所有排列

        printf("%s
", res[i]);

        free(res[i]); // 释放内存空间

    }

    free(s);

    return 0;

}




如何实现程序语句的重复执行?(C++语言)
二:怎样在用户输入错误情况下重新提示?while(bc>20){...把这个循环放在画图代码的前面 ...提示用户重新输入 ...接受用户输入的bc } ...画正方形 三:这里用递归不好。因为会大大降低效率——这里完全可以用while循环来实现。虽然用递归对这个程序不会有什么大的影响,但是要养成考虑效率的习惯。...

...字母中的任何一个,且可重复,用C语言怎样编程实现?
你是想罗列出所有可能的组合吧?那么这个代码应该可以实现:include<stdio.h> void main(){ int i,j;for(i=0;i<3;i++){ for(j=0;j<3;j++)printf("%c%c ",'a'+i,'a'+j);} putchar('\\n');} 这是个比较笨的方法,但是我是在想不出其他的方法,还望谅解。该程序可以实现你...

易语言文本去掉重复的,留下一个重复的
这个是理想情况。 输出文本 = 输出文本 + 数组 [i] + #换行符 ' 所以直接输出 .否则 .如果真 (寻找文本 (重复的文本, 数组 [i], , 真) = -1) ' 如果存在多个同样的文本,先判断,然后加入“重复的文本”里面。。如果在里面没有重复就算不重复了(这么写是因为,重复的...

c语言用循环语句实现重复循环
你的思路没问题,有问题的可能是这一句while(c);,假如你输入的是非零的c,那么存在隐式转换就可能变成while(1);了,所以就退出了。另外我想说一句的是,我很长时间没接触c语言,现在全都是asp.net和c#,说的对不对的你多试试。再就是编程序不要为了简化而简化,更不要为了显示“水平”而简化...

如何用c语言判断一组字符中有多少个重复的字符串,如a,a,c,c,b有2个
\/\/ 这里是找重复的字符 \/\/ 找重复的字符串比较麻烦了char str[]={"aaccb"}; \/\/ 如果包含a~z之外的字符要另外考虑,还有大小写int az[26]={0};\/\/然后遍历字符串,for(int i=0;i<strlen(str);i++) az[str[i]-'a']++; \/\/ 然后int count=0;for (int j=0;j<26...

C语言中如何循环取数组中的值,比如数组中有10个数,从第一个取到第十个...
用for循环或者while循环呀,然后用数组的长度作为循环跳出的判断条件。根据楼主的需求,只要到达数组末尾的时候,不跳出循环,而改为初始化为0就可以了

在C语言中如何实现“让一句话在屏幕上重复不断的打印出来直至我设置的那...
\/\/ 参数:年、月、日、时、分、秒和你要显示的那句话 void MyPrint(int year, int month, int day, int hour, int minute, int second, char *text){ while (text != NULL){ time_t t = time(NULL);struct tm *now = localtime(&t);if (year - 1900 == now->tm_year && ...

自己的英文和之前的发表的有部分语言重复可以吗
可以的,只需要在末尾处写上以上内容参考哪个文献所得出来的结论即可。

关于c语言switch case语句如何一直重复使用直到用户主动退出的问题_百 ...
switch case语句一直重复使用直到用户主动退出,这种行为,需要采用循环方式才可以达到。switch case是顺序执行语句,执行完选择项后,就会结束这段语句。C语言提供三种循环语句方式: for (), while(), do .. while()根据代码行为特点,可选用相应的语句来实现,如,本题目用do .. while()最合适 ...

C语言中,怎样判断一个数组中是否有重复元素呢?最好用程序实现
import org.apache.commons.lang.ArrayUtils;public boolean isDupInArray(Object[]array){ if(ArrayUtils.isEmpty(array)==true){ return false;} for(Object obj:array){ if(ArrayUtils.indexOf(array,obj)!=ArrayUtils.lastIndexOf(array,obj)){ return true;} } return false;} ...

攸县19733521139: 用C语言解决具有重复项的数组全排列问题 -
宇文洪知甘: 那还是排列问题,把比较的条件设置成>= 或是

攸县19733521139: 如何用C语言实现有重复的字符排列组合? -
宇文洪知甘: 可自行百度"排列组合".对于你举的例子,因为不存在重复字符,共有A(4,4) = 256种结果.如果输入字符中有重复项,需要加入判断重复并剔除的功能.可定义一个2维数组,每次排列完后对数组内的重复项进行删除.

攸县19733521139: c语言 重复字符全排列 -
宇文洪知甘: 给程序加点注释,让别人也稍微明白一下 呵呵,你确定自己的程序在思想上之类的没有错误么? 在perm后面的for中调用circle_*的函数的时候,你传入的l总是会比i大的 这样一来在函数中m接收l,i接收i 然后再circle_*中的for循环的判断条件是i-m应该是不会执行吧至于你说的那个功能我也不是很清楚 呵呵,能帮的就只有这些了

攸县19733521139: 全排列用C语言实现 -
宇文洪知甘: 给,已经编译运行确认: #include<stdio.h> #include<string.h> char a[20]; int lenth; long count=0; void main() {void move(int,int); int i,j=0; printf("input:");gets(a); lenth=strlen(a); for(i=0;i<lenth;i++) move(j,i);//move a[i] to the front of a[j]; printf("\...

攸县19733521139: 如何用C语言编写1234的全排列 -
宇文洪知甘: #include <stdio.h> void main() {int i=0,j=0,k=0,l=0,count=0;for(i=1;i<=4;i++){for(j=1;j<=4;j++)if(j!=i)for(k=1;k<=4;k++)if(k!=i&&k!=j)for(l=1;l<=4;l++)if(l!=i&&l!=j&&l!=k){ count++;printf("\n\t第%2d个 %d %d %d %d",count,i,j,k,l);}}putchar('\n'); }

攸县19733521139: 用c语言实现 ABCDE按照全排列输出所有结果 -
宇文洪知甘: #include <stdio.h> #include <stdlib.h> void main() {char i,j,k,m,n;for(i='A';i<='E';i++)for(j='A';j<='E';j++)for(k='A';k<='E';k++)for(m='A';m<='E';m++)for(n='A';n<='E';n++)if(i!=j&&i!=k&&i!=m&&i!=n&&j!=k&&j!=m&&j!=n&&k!=m&&k!=n&&m!=n)...

攸县19733521139: C语言实现非递归全排列 -
宇文洪知甘: 这个函数你可以这样理解,要对一个长度为n的数组全排列,用位置来考虑,首先将所有元素放入第一个位置,实现了第一个位置的全排列,然后对于每一个剩下的n-1个位置再进行全排列.直到最后没有位置了 全排列结束.

攸县19733521139: c语言中怎样把n个数排列 得到所有排列情况 -
宇文洪知甘: #includeinline void Swap(char& a, char& b) {// 交换a和b char temp = a; a = b; b = temp; } void Perm(char list[], int k, int m) { //生成list [k:m ]的所有排列方式 int i; if (k == m) {//输出一个排列方式 for (i = 0; i putchar(list[i]); putchar('\n'); } else // list[k:m ]有...

攸县19733521139: C语言编程序:要求任给一个一维数组,其中重复的元素只保留一个,然后把互不重复的按照升序排列! -
宇文洪知甘: 改了一下顺序,先排列,后删除重复的元素# include <stdio.h> void sort(int a[],int n); int del(int a[],int n); main() { int a[1000],i,n; printf("How many numbers:"); scanf("%d",&n); printf("input %d numbers:\n",n); for(i=0;i<n;i++) scanf("%d",&a...

攸县19733521139: C语言!!!构建全排列!!!速求!!!要有错排的!!!代码好了有追加分!!! -
宇文洪知甘: vc下编译通过 赋运行图 地址:#includechar a; int b[2] = ,x=0; char c[999]; void sr() { do { a = getchar(); if(a>='0' && a { b[0]++; c[x] = a; x++; } else if((a>='a' && a='A' && a b[1]++; } while(a != 10); } void pl() { int i,j,k; for(i=0; i for(j=i; j { if(c[i] { k = c[j]; c[j] ...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网