回溯入门题,数据所有排列方式(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;
}
相关文章
|
14天前
|
存储 程序员 编译器
C 语言中的数据类型转换:连接不同数据世界的桥梁
C语言中的数据类型转换是程序设计中不可或缺的一部分,它如同连接不同数据世界的桥梁,使得不同类型的变量之间能够互相传递和转换,确保了程序的灵活性与兼容性。通过强制类型转换或自动类型转换,C语言允许开发者在保证数据完整性的前提下,实现复杂的数据处理逻辑。
|
2月前
|
安全 编译器 C语言
C++入门1——从C语言到C++的过渡
C++入门1——从C语言到C++的过渡
66 2
|
14天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
66 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
15天前
|
存储 数据管理 C语言
C 语言中的文件操作:数据持久化的关键桥梁
C语言中的文件操作是实现数据持久化的重要手段,通过 fopen、fclose、fread、fwrite 等函数,可以实现对文件的创建、读写和关闭,构建程序与外部数据存储之间的桥梁。
|
18天前
|
存储 数据建模 程序员
C 语言结构体 —— 数据封装的利器
C语言结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起,形成一个整体。它支持数据封装,便于管理和传递复杂数据,是程序设计中的重要工具。
|
24天前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
51 11
|
4月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
417 0
|
2月前
|
存储 C语言 C++
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
|
2月前
|
存储 Java 编译器
初识C语言1——C语言入门介绍
初识C语言1——C语言入门介绍
33 1
|
2月前
|
存储 C语言
深入C语言内存:数据在内存中的存储
深入C语言内存:数据在内存中的存储