回溯入门题,数据所有排列方式(c语言)

简介: 回溯入门题,数据所有排列方式(c语言)

题目:

首先输入一个数字n,连续输入n个不同的整数,输出所有能排列的可能。

整体思路

我们将需要的数写进数组中,写一个函数进行排序,数组的下标从0开始,n-1结尾,将数组下标进行传参。

代码如下:

int main()
{
  int arr[1000];
  int n = 0;
  printf("请输入数字个数:");
  scanf("%d", &n);
  printf("请输入%d个数字:\n", n);
  for (int i = 0; i < n; i++)
  {
    scanf("%d", &arr[i]);
  }
  printf("所有排列如下:\n");
  permut(arr, 0, n-1);
  return 0;
}

函数接收如下

1. void permut(int* arr,int p, int q)
2. {
3. 
4. }

排序函数的实现

那我们要如何实现这个函数?


让我们先看一个简单的例子,有三个数1,2,3,他们的所有排列可能如下:

1  2  3

1  3  2

2  1  3

2  3  1

3  1  2

3  2  1

总计6种


我们可以将他们看成三组,分别是以1,2,3开头的,后面两个数做所有的排列方式,我们简称全排列

那我们不妨发散一下,如果有更多数呢?比如1,2,3,4,5,6

分别以1,2,3,4,5,6开头,剩下的数进行全排列。


那我们如何找到这六个数并放到最前面来呢?

我们可以写一个循环,让第一个数也就是下标为0,依次与后面的数进行交换,这里写一个交换函数swap。

void permut(int* arr,int p, int q)
{
    int i=0;
  for (i = p;i <= q;i++)
  {
    swap(&arr[p], &arr[i]);
  }
}
void swap(int* a, int* b)
{
  int temp = *a;
  *a = *b;
  *b = temp;
}

在交换完之后,剩下的数再做全排列,进入下一层递归,第一层是下标p到q,下一层则是p+1到q。

void permut(int* arr, int p, int q)
{
    int i=0;
  for (i = p;i <= q;i++)
  {
    swap(&arr[p], &arr[i]);
        permut(arr, p+1, q);
  }
}

在下标为p+1到q完成全排列之后,需要把第二个数提到最前面来,那自然需要把排列结果恢复上一次调换之前的情况,再返回上一层递归:

void permut(int* arr, int p, int q)
{
    int i=0;
  for (i = p;i <= q;i++)
  {
    swap(&arr[p], &arr[i]);
        permut(arr, p+1, q);
  }
}

但这个递归要怎么停止呢?

当只有一个数字做全排列的时候,他的全排列等于他本身,递归也就停止,即p==q,这个时候可以把排列打印出来了,写一个打印函数。

void permut(int* arr, int p, int q)
{
  int i = 0;
  
  if (p == q)
  {
    print(arr, q);
  }
  else
  {
    for (i = p;i <= q;i++)
    {
      swap(&arr[p], &arr[i]);
      permut(arr, p + 1, q);
      swap(&arr[i], &arr[p]);
    }
  }
}
void print(int* arr, int n)
{
  int i=0;
  for (i = 0;i <= n;i++)
  {
    printf("%d ",arr[i]);
  }
}

完整代码

#include<stdio.h>
 
void swap(int* a, int* b)
{
  int temp = *a;
  *a = *b;
  *b = temp;
}
 
void print(int* arr, int n)
{
  int i=0;
  for (i = 0;i <= n;i++)
  {
    printf("%d ",arr[i]);
  }
}
 
void permut(int* arr, int p, int q)
{
  int i = 0;
  
  if (p == q)
  {
    print(arr, q);
  }
  else
  {
    for (i = p;i <= q;i++)
    {
      swap(&arr[p], &arr[i]);
      permut(arr, p + 1, q);
      swap(&arr[i], &arr[p]);
    }
  }
}
 
int main()
{
  int arr[1000];
  int n = 0;
  printf("请输入数字个数:");
  scanf("%d", &n);
  printf("请输入%d个数字:\n", n);
  for (int i = 0; i < n; i++)
  {
    scanf("%d", &arr[i]);
  }
  printf("所有排列如下:\n");
  permut(arr, 0, n - 1);
  return 0;
}
相关文章
|
1月前
|
安全 编译器 C语言
C++入门1——从C语言到C++的过渡
C++入门1——从C语言到C++的过渡
52 2
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
370 0
|
1月前
|
存储 C语言 C++
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
|
1月前
|
存储 Java 编译器
初识C语言1——C语言入门介绍
初识C语言1——C语言入门介绍
30 1
|
1月前
|
存储 C语言
深入C语言内存:数据在内存中的存储
深入C语言内存:数据在内存中的存储
|
2月前
|
C语言
C语言程序设计核心详解 第二章:数据与数据类型 4种常量详解 常见表达式详解
本文详细介绍了C语言中的数据与数据类型,包括常量、变量、表达式和函数等内容。常量分为整型、实型、字符型和字符串常量,其中整型常量有十进制、八进制和十六进制三种形式;实型常量包括小数和指数形式;字符型常量涵盖常规字符、转义字符及八进制、十六进制形式;字符串常量由双引号括起。变量遵循先定义后使用的规则,并需遵守命名规范。函数分为标准函数和自定义函数,如`sqrt()`和`abs()`。表达式涉及算术、赋值、自增自减和逗号运算符等,需注意运算符的优先级和结合性。文章还介绍了强制类型转换及隐式转换的概念。
|
3月前
|
C语言
C语言------程设设计入门
这篇文章是C语言程序设计的入门教程,涵盖了C程序的实现过程、VC集成开发环境的使用、基本数据类型的使用、格式控制字符的作用,以及通过示例代码演示了如何使用printf()函数输出不同类型的数据。
C语言------程设设计入门
|
3月前
|
存储 C语言
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
53 15
|
3月前
|
C语言
【C语言】在限制定条件下数据移动
【C语言】在限制定条件下数据移动
38 1
|
3月前
|
存储 C语言
【C语言】C语言-设备管理系统(源码+数据文件)【独一无二】
【C语言】C语言-设备管理系统(源码+数据文件)【独一无二】
104 4