补充全排列算法C语言实现

合集下载

c语言算法100例

c语言算法100例

c语言算法100例以下是一些经典的C语言算法题目,总共提供100个例子供你练习和学习:1.编写一个程序,计算并输出斐波那契数列的前20个数。

2.编写一个程序,判断一个数是否为素数。

3.编写一个程序,计算并输出一个数的阶乘。

4.编写一个程序,实现两个数的交换(不使用第三个变量)。

5.编写一个程序,找出一个数组中的最大值。

6.编写一个程序,将一个字符串反转。

7.编写一个程序,判断一个字符串是否为回文字符串。

8.编写一个程序,实现冒泡排序算法对一个数组进行排序。

9.编写一个程序,实现二分查找算法在一个有序数组中查找指定的元素。

10.编写一个程序,计算并输出斐波那契数列的第n个数。

11.编写一个程序,将一个二维数组顺时针旋转90度。

12.编写一个程序,计算并输出一个数的平方根。

13.编写一个程序,判断一个字符串中是否包含重复字符。

14.编写一个程序,实现插入排序算法对一个数组进行排序。

15.编写一个程序,将一个有序数组合并为一个有序数组。

16.编写一个程序,判断一个数是否为完全数(即所有因子之和等于该数本身)。

17.编写一个程序,计算并输出一个数的倒数。

18.编写一个程序,判断一个字符串是否是另一个字符串的子串。

19.编写一个程序,实现选择排序算法对一个数组进行排序。

20.编写一个程序,计算并输出两个数的最大公约数。

21.编写一个程序,实现快速排序算法对一个数组进行排序。

22.编写一个程序,将一个字符串中的所有空格替换为指定的字符。

23.编写一个程序,判断一个数是否是回文数。

24.编写一个程序,计算并输出两个数的最小公倍数。

25.编写一个程序,实现归并排序算法对一个数组进行排序。

26.编写一个程序,判断一个字符串是否是有效的括号串。

27.编写一个程序,计算并输出一个数的立方根。

28.编写一个程序,实现堆排序算法对一个数组进行排序。

29.编写一个程序,判断一个数是否是质数。

30.编写一个程序,计算并输出一个数的二进制表示。

c#实现的几种排序方法

c#实现的几种排序方法

c#实现的⼏种排序⽅法1.经典排序算法 – 插⼊排序Insertion sort插⼊排序就是每⼀步都将⼀个待排数据按其⼤⼩插⼊到已经排序的数据中的适当位置,直到全部插⼊完毕。

插⼊排序⽅法分直接插⼊排序和折半插⼊排序两种,这⾥只介绍直接插⼊排序,折半插⼊排序留到“查找”内容中进⾏。

图1演⽰了对4个元素进⾏直接插⼊排序的过程,共需要(a),(b),(c)三次插⼊。

public void Sort(int[] arr){for (int i = 1; i < arr.Length; i++){int t = arr[i];int j = i;while ((j > 0) && (arr[j - 1] > t)){arr[j] = arr[j - 1];//交换顺序--j;}arr[j] = t;}}折半排序算法是对直接插⼊算法的⼀种优化,优化的核⼼是:通过折半查看有序数组中间位置的数值(a)与待插⼊的数值(temp)的⼤⼩,如果a>=temp,则转向折半的左区间继续折半查找;如果a<temp,则转向折半后的右区间继续折半查找。

直到左右下标相同时,此时折半的下标也指向相同的位置,再做最后⼀次循环,最终的结果是:左右下标相差1,并且原来左侧的下标指向⼤于temp的位置,原来右侧的下标指向了⼩于temp的位置,即:array[biggerIndex] < temp < array[smallerIndex]。

//折半排序算法(传递待排数组名,即:数组的地址。

故形参数组的各种操作反应到实参数组上)private static void BinaryInsertionSortFunction(int[] array){try{int smallerIndex = 0; //记录有序数组的起始位置int biggerIndex = 0; //记录有序数组的终⽌位置int midIndex = 0; //记录获取有序数组的中间位置(折半法的关键:折半的位置)int temp; //记录带排的数值for (int i = 1; i < array.Length; i++) //循环向有序数组中插⼊数值(i从1开始,因为操作的是同⼀个数组){temp = array[i]; //记录待插⼊有序数组的数值biggerIndex = i - 1;//当smallerIndex==biggerIndex时,进⼊最后⼀次循环:smallerIndex指向⼤于temp的数组位置,biggerIndex指向⼩于temp的数组位置while (smallerIndex <= biggerIndex){midIndex = (smallerIndex + biggerIndex) / 2; //确定折半的位置if(array[midIndex] >= temp) //折半位置的数值 >= temp{biggerIndex = midIndex - 1; //biggerIndex以midIndex为基础向前移动⼀位}else{smallerIndex = midIndex + 1; //smallerIndex以midIndex为基础向后移动⼀位}}for (int j = i - 1; j >biggerIndex; j--) //将有序数组中⼤于temp的数值分别向后移动⼀位{array[j + 1] = array[j]; //}array[biggerIndex + 1] = temp; //将temp插⼊biggerIndex + 1,因为此时array[biggerIndex]<temp<array[smallerIndex]}}catch (Exception ex){ }}2. //选择排序public static void SelectionSort(int[] num){int min, temp;for (int i = 0; i < num.Length-1; i++){min = i;for (int j =i+1; j < num.Length; j++){if (num[j] < num[min]){min = j;}}temp = num[i];num[i] = num[min];num[min] = temp;}}3. //冒泡排序(Bubble Sort)的基本思想是:将相邻的记录的关键码进⾏⽐较,若前⾯记录的关键码⼤于后⾯记录的关键码,则将它们交换,否则不交换。

全排列递归算法c语言

全排列递归算法c语言

全排列递归算法c语言
全排列是一种将一组元素进行排列得到所有可能的组合的算法。

递归是一种重复调用函数本身的方法,可以用来实现全排列算法。

以下是一个使用递归算法实现全排列的C语言代码示例:// 交换数组中两个元素的位置
// 递归生成全排列
// 将第i个元素与第start个元素交换位置 // 递归生成剩余元素的全排列
// 恢复数组的原始顺序
这段代码使用了递归的方式生成数组 `arr` 的全排列。

`permute` 函数接受一个数组、起始位置 `start` 和结束位置`end` 作为参数。

在每一次递归调用中,它将当前位置的元素与后续位置的元素依次交换,并递归生成剩余元素的全排列。

当`start` 等于 `end` 时,表示已经完成了一种排列,将其打印出来。

运行上述代码,将会输出以下结果:
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
```
这些结果是给定数组 `[1, 2, 3]` 的所有全排列。

全排列的生成算法

全排列的生成算法

全排列的生成算法全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。

任何n 个字符集的排列都可以与1~n的n个数字的排列一一对应,因此在此就以n个数字的排列为例说明排列的生成法。

n个字符的全体排列之间存在一个确定的线性顺序关系。

所有的排列中除最后一个排列外,都有一个后继;除第一个排列外,都有一个前驱。

每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法。

全排列的生成法通常有以下几种:字典序法递增进位数制法递减进位数制法邻位交换法递归类算法1.字典序法字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。

例如对于5个数字的排列12354和12345,排列12345在前,排列12354在后。

按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是54321。

字典序算法如下:设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即j=max{i|pi<pi+1}2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)3)对换pi,pk4)再将pj+1......pk-1pkpk+1pn倒转得到排列p’’=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。

例如839647521是数字1~9的一个排列。

从它生成下一个排列的步骤如下:自右至左找出排列中第一个比右边数字小的数字4 839647521在该数字后的数字中找出比4大的数中最小的一个5 839647521将5与4交换 839657421将7421倒转 839651247所以839647521的下一个排列是839651247。

全排列算法思路解析

全排列算法思路解析

全排列算法思路解析
全排列算法是一种基础的算法,用于对给定的一组数据进行全排列。

在程序设计中,全排列算法常常被运用于组合、排序等场景,是一种十分常见的算法。

算法流程如下:
1.设将要排列的元素存在一个字符串S中;
2.将S中的每个字符依次与它后面的字符交换;
3.当S中只剩下一个字符时,输出S;
5.当排列到最后一个元素时,依次输出字符串S的每一个字符,得到一个新的排列。

在算法流程的执行过程中,我们必须清楚的是,每一次交换操作都会对S字符串进行修改。

此外,我们还需要对S字符串的长度和当前元素的位置进行追踪和控制,保证每一个元素都能够交换到相应的位置上。

全排列算法的时间复杂度很高,是O(n!),所以在实际使用中需要耐心地等待程序的执行结果。

总的来说,全排列算法虽然看似简单,但它将我们的编程思维与编程技巧提高到了一个新的水平。

在日常编程的实践中,我们将许多的算法融入到自己的程序中,体现出了我们的编程思维严谨、技巧娴熟,是一种十分有意义的学习与实践过程。

c语言顺序结构例题

c语言顺序结构例题

C语言顺序结构例题
在C语言中,顺序结构是最基本的程序结构,它按照代码的顺序逐行执行。

下面是一个简单的顺序结构例题,可以帮助你更好地理解这种结构。

题目:编写一个程序,计算并输出1到n之间所有整数的和。

在这个程序中,我们首先定义了两个变量n和sum,分别表示输入的正整数和1到n之间所有整数的和。

然后使用printf函数提示用户输入一个正整数n,并使用scanf函数读取用户输入的值。

接下来使用for循环计算1到n之间所有整数的和,并将结果存储在sum变量中。

最后使用printf函数输出结果。

需要注意的是,在这个程序中,我们使用了顺序结构来执行代码。

首先执行了printf函数,提示用户输入一个正整数n,然后执行了scanf函数读取用户输入的值。

接着执行了for循环计算1到n之间所有整数的和,并将结果存储在sum 变量中。

最后执行了printf函数输出结果。

这些代码按照顺序逐行执行,没有使用任何控制语句来改变程序的执行流程。

c++ 排列组合 函数

c++ 排列组合 函数

c++ 排列组合函数排列组合函数是指在数学中用于计算集合中元素的排列和组合的函数,通常用于处理概率论、组合数学、统计学等方面的问题。

在C++语言中,可以使用标准库中的头文件<cstdlib>和<algorithm>实现排列组合函数。

本文将介绍 C++中常用的排列组合函数及其应用。

一、排列函数(permutation)在数学中,排列是从一个集合中取出一些元素(可重复或不重复),按照一定的顺序排列组成不同的序列,称为排列。

比如说,从1、2、3三个元素中任意取两个元素进行排列,那么可能得到的所有排列如下:1,21,32,12,33,13,2由于每个元素只能在一个位置上,因此这是不同的排列。

总共有6种不同的排列,这个数就是集合{1, 2, 3}的排列数,记为A(3, 2)。

C++中求排列数的函数为permutation,有两种实现方式,分别为next_permutation 函数和prev_permutation函数。

顾名思义,next_permutation函数是指下一个排列,prev_permutation函数是指上一个排列。

template <class BidirIt>bool next_permutation(BidirIt first, BidirIt last);其中first和last是迭代器,表示要排列的集合的起始位置和结束位置,返回值为bool型,表示是否有下一个排列。

如果有下一个排列,那么函数会将集合重新排列成下一个排列,并返回true,如果没有下一个排列,那么函数会将集合重新排列成第一个排列,并返回false。

下面是一个简单的示例代码:输出结果为:1 2 31 3 22 1 32 3 13 1 23 2 1prev_permutation函数与next_permutation函数相反,它是用于计算前面的排列,即上一个排列。

如果有前一个排列,函数就返回true,并将集合重新排列成前一排列;如果没有前一个排列,函数将返回false,并将集合排列成最后一个排列。

c语言递归实现全排列

c语言递归实现全排列

c语言递归实现全排列在计算机科学中,递归是一种常见的编程技巧,指程序在执行过程中调用自身的过程。

递归的优点是能够简洁地表达某些算法,缺点是增加了程序的内存消耗和执行时间。

全排列是一种经典的计算问题,即把给定的一组数全排列。

一、基本概念1.1 全排列全排列是一种组合数学上非常重要的概念,是一组数的所有可能的排列的总和。

例如,1、2、3三个数的全排列是:123、132、213、231、312、321。

n个不同元素的全排列个数为n的阶乘n!。

1.2 递归递归是一种程序设计或算法设计的方法,可以让一个函数调用自身。

递归通常特别简洁,但对内存产生较高负荷。

递归算法可以递归计算任何递归可定义的函数。

递归算法通常由两个部分组成:基线条件和递归条件。

如果递归条件得到基线条件,则停止递归并返回结果。

二、算法实现n个元素的全排列可以看作是把第一个元素与所有元素交换,得到n个排列中以第一个元素开头的排列。

然后递归求剩余的n-1个元素的排列后,再将它们插入到上一步求得的排列中,就得到了所有元素的全排列。

以n=3为例,其全排列为 (1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,2,1),(3,1,2)。

比如,我们先固定第一个数是1,然后求剩余的数2,3的排列。

得到的排列有(2,3)和(3,2)。

我们再把1插入到每个排列的所有可能位置,即得到(1,2,3)和(1,3,2)。

同样的,我们再固定第一个数是2和3,分别求剩余的数的排列,再将2和3插入到每个排列的所有可能位置即可。

代码实现如下:#include <stdio.h>#include <stdlib.h>// 递归实现全排列void perm(int list[], int k, int m) {if (k == m) {for (int i = 0; i <= m; i++) {printf("%d", list[i]);}printf("\n");} else {for (int i = k; i <= m; i++) {// 把第i个数交换到第一个位置int temp = list[k];list[k] = list[i];list[i] = temp;// 求剩下元素的排列perm(list, k+1, m);// 把元素交换回来temp = list[k];list[k] = list[i];list[i] = temp;}}}2.2 非递归实现的思路非递归实现的思路是用一个栈来存储未处理的子问题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

字符串全排列算法C语言实现
问题描述:
输入一个字符串,打印出该字符串中字符的所有排列。

输入:
123
输出:
123
132
213
231
312
321
问题分析:
现象分析:
这种问题,从直观感觉就是用递归方法来实现即:把复杂问题逐渐简单化,进而得出具体代码实现。

(如何发现一个问题可以使用递归方式来解决?经分析可以发现:M 个数的排列方法与N(N>M)个数的排列方法没有区别,处理方法与数据的个数没有关系。

处理方法的一致性,就可以采用递归)。

3个数(123)排列,第一位1不动,剩下两个数(23)的排列,只要相互颠倒一下,就可以出现关于1开头的所有排列 123 132
把2换到第一位,保持不动,剩下的两个数(13)的排列,只要相互颠倒一下,就可以出现关于2开头的所有排列 213 231
同理,把3换到第一位,可得到 312 321
扩展:
把3个数的所有排列,前面加一个4,就可以得到关于4开头的所有的排列4123
4132
4213
4231
4312
4321
若把4与后续数据中的任意一个数据交换,通过完成对后续三个数的全排列,就可以得到相应的数开头的四数的排列。

总结:
对4个数的排列,可以转换成首位不动,完成对3个数的排列
对3个数的排列,可以转换成首位不动,完成对2个数的排列
对2个数的排列,可以转换成首位不动,完成对1个数的排列
对于1个数,无排列,直接输出结果
算法实现说明:
对n个数的排列,分成两步:
(1)首位不动,完成对n-1个数的排列,
(2)循环将后续其他数换到首位,再次进行n-1个数的排列
注:排列完成后,最终的串要与原串相同
C语言代码实现:
#include <stdio.h>
#include <string.h>
//将串左移一位,首位存到末尾。

void shift( char *s )
{
if ( !s||!s[0] ) return ; //security code . null string
char ch=s[0];
int i=0;
while( s[++i] )
s[i-1]=s[i] ;
s[i-1]=ch;
}
//本函数对于一个已排序好的数据进行全排列
void permutation(char list[], int head ) {
int i,len;
len=strlen(list) ;
if ( len-head == 1 ) //后续没有再排列的,则输出排列数据
{
printf( "%s\n", list );
}
else
{
for (i = k; i<len; i++) //从当前位置开始,每个数当一次队首,并进行后续排列
{
permutation(list, head+1); //后续串排列
shift( &list[head] ); //轮流为当第一
}
}
}
void pailie( char *str )
{
permutation( str, 0 ); //排列算法,从串的第几位开始排列
}
int main()
{
char str[]="1234";
pailie(str);
return 0;
}
带重复数据的排列问题:
如果有重复数据出现在待排列的数据中,则,若某数已经当过队首,则与其相同的数再当队首是一样的排列结果,如:1233进行全排列
当第一个3当队首时,会出现一次全排列
第二个3当队首时,会出现与第一个3当队首相同的全排列,因此,只需要保证此数据出现过队首时,不要让其再当队首就可以解决问题了。

代码实现:
//检查chk位的数据是否曾经当过队首
/*
list:待排列的全部数据
chk:待检查的位置
begin:已当过队首的数据的起始位置。

因为是移位,所以,从begin检查到list尾就可以了。

*/
is_dup( char *list, int begin, int chk )
{
int i;
for( i=begin; list[i]; i++ )
if ( list[chk] == list[i] )
return 1;
return 0;
}
void permutation(char list[], int k) {
int i,len;
len=strlen(list) ;
if ( len-k == 1 ) //后续没有再排列的,则输出排列数据
{
printf( "%s\n", list );
}
{
for (i = k; i<len; i++)
{
if ( !is_dup(list, len-(i-k), k ) ) //如果没有当过队首,则排列之permutation(list, k+1);
shift( &list[k] );
}
}
}
采用数据交换方式实现的全排列,带去重的代码:
//交换两个数的位置
void swap(char *a, char *b) {
char m;
m = *a;
*a = *b;
*b = m;
}
//检查某数据是否曾经当过队首(在已交换过的数据中进行查找)
/*
list:待排列的全部数据
end:当前交换的位置
begin:待交换的位置
*/
int is_dup( char *s, int end, int begin )
{
int i=0;
for( i=end;i>begin;i-- )
if ( s[end] == s[i-1] )
return 1;
return 0;
}
void permutation(char list[], int k) {
int i,len;
len=strlen(list) ;
if ( len-k == 1 ) //后续没有再排列的,则输出排列数据
{
printf( "%s\n", list );
}
{
for (i = k; i<len; i++)
{
if ( !is_dup ( list,i,k ) ) //如果没有重复的,则进行相应的排列,否则跳过之,因为:相同的数据当队首,交换没有意义
{
swap(&list[k], &list[i]);//交换
permutation(list, k+1); //后续串排列
swap(&list[i], &list[k]);//恢复
}
}
}
}
void pailie( char *str )
{
permutation( str, 0 ); //排列算法,从串的第几位开始排列
}
int main()
{
char str[]="1234";
pailie(str);
return 0;
}。

相关文档
最新文档