perfect_shuffle的C++实现

本文详细介绍了如何使用C++实现完美洗牌算法,并通过关键函数`cycle_leader`达到O(n)的时间复杂度。算法步骤包括计算圈大小、利用STL的rotate函数进行循环移位、对特定圈进行循环交换等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天花了点时间实现了C++版的perfect_shuffle算法,具体代码如下:

//compiled with g++
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cassert>
using namespace std;

void cycle_leader(vector<int> &a,int from, int mod) {  
  for (int i = from * 2 % mod;i != from; i = i * 2 % mod)
     swap(a[from],a[i]);
}

void perfect_shuffle(vector<int> &a,int n){
   int n2,m,i,k,t;
   vector<int>::iterator iter = a.begin()+1; //exclude index 0
   for(;n > 1;){
      //step 1
      n2 = n * 2;
      for(k = 0,m = 1; n2 / m >=3; ++k,m *= 3)
         ;
      m /= 2;
      // 2m = 3^k - 1 , 3^k <= 2n < 3^(k + 1)

      //step 2   STL/algorithm-rotate
      rotate(iter+m, iter+n, iter+m+n ); //right cyclic shift of the index[m+1,...,n+m] O(n)
      
      //step 3
      for(i = 0,t = 1;i < k; ++i,t *= 3)
         cycle_leader(a,t,m * 2 +1);
      
      //step 4
      iter += (m * 2);
      n -= m;
   }
   //n = 1
   swap(a[1],a[2]);
}

int main(){
   vector<int > a;
   a.push_back(0);//to make index start from 1
   int num = 0,length = 0;
   cout<<"Please input your number to be shuffled and '0' to end up \n";
   cin>>num;
   while(num != 0){
      a.push_back(num);
      cin>>num;
   }
   cout<<"The input number is \n";
   copy(a.begin()+1,a.end(),ostream_iterator<int> (cout," "));
   cout<<"\n";
   
   length = a.size();
   assert(length % 2 == 1); //the size of input number is even
   perfect_shuffle(a,length / 2);
   //cycle_leader(a,1,9);
   cout<<"After shuffered,the number is  \n";
   copy(a.begin()+1,a.end(),ostream_iterator<int> (cout," "));
   cout<<"\n";
}

关键的算法就是cycle_leader,这是整个算法实现O(n)复杂度的功劳所在,为了实现这个圈只需要在一个循环中不停的交换下标为from和i(不停的更新)的元素,

### C++ 中 `to_string` 函数的用法和示例 C++ 中的 `std::to_string` 函数是一个用于将数值类型转换为字符串的强大工具。它定义在 `<string>` 头文件中,支持多种基本数据类型的转换,包括整数、浮点数等[^1]。 #### 用法 - **函数原型**:`string to_string (T value);` - 其中 `T` 是一个模板参数,可以是任何可转换为字符串的基本类型。 - **返回值**:该函数会返回一个表示传入数值的字符串对象。 #### 支持的数据类型 `std::to_string` 支持以下数据类型的转换: - 整型(int, long, long long) - 浮点型(float, double) - 无符号整型(unsigned int, unsigned long, unsigned long long) #### 示例代码 下面是一些使用 `std::to_string` 的典型例子: ```cpp #include <iostream> #include <string> int main() { // 将浮点数转换为字符串 std::string pi = "pi is " + std::to_string(3.1415926); // 将整数表达式的结果转换为字符串 std::string perfect = std::to_string(1+2+4+7+14) + " is a perfect number"; // 输出结果 std::cout << pi << '\n'; std::cout << perfect << '\n'; return 0; } ``` 在这个例子中,我们首先将浮点数 `3.1415926` 转换成了字符串,并将其附加到 `"pi is "` 后面。接着,我们将一系列整数相加的结果(28)转换成字符串,并连接上描述文本。最后,通过 `std::cout` 打印出这两个字符串[^2]。 #### 注意事项 - 当处理非常大的数字或需要特定格式化时,可能需要考虑其他方法或者使用额外的库来满足需求。 - `std::to_string` 在处理浮点数时,默认情况下可能会显示较多的小数位数,这取决于具体的实现。如果需要控制精度,可以先使用 `std::ostringstream` 设置精度再进行转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值