扑克牌洗牌有多种算法:
第1个:每次从原数组A取出范围[1,i]的数放入B数组。 缺点是每次都要将数组i后面的元素进行移动。 是一个o(n2)算法
void xipai(int n){ // o(n2)
int x = n;
int idx = 1;
while(n){
int t = rand() % n;
B[idx++] = A[ t + 1];
for(int i = t + 1; i < n; i++){
A[i] = A[i + 1];
}
n--;
}
for(int i = 1; i <= x; i++){
cout << B[i] << " ";
}
}
第2种:每次取范围[1,i - 1]的数, 然后与最后一个元素做交换。这样的复杂度优化成o(n), 在C++ STL可以直接用random_shuffle(), 或者自己造轮子,如代码。
void xipai2(int n){ // o(n)
// random_shuffle(A + 1, A + n + 1);
for(int i = n; i > 1; i--){
int t = rand() % (i - 1);
int tt = A[t + 1];
A[t + 1] = A[i];
A[i] = tt;
}
for(int i = 1; i <= n; i++){
cout << A[i] << " ";
}
}
完整代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 60;
int A[N];
int B[N];
void ini(){
for(int i = 1; i <= 54; i++){
A[i] = i;
}
}
void xipai(int n){ // o(n2)
int x = n;
int idx = 1;
while(n){
int t = rand() % n;
B[idx++] = A[ t + 1];
for(int i = t + 1; i < n; i++){
A[i] = A[i + 1];
}
n--;
}
for(int i = 1; i <= x; i++){
cout << B[i] << " ";
}
}
void xipai2(int n){ // o(n)
// random_shuffle(A + 1, A + n + 1);
for(int i = n; i > 1; i--){
int t = rand() % (i - 1);
int tt = A[t + 1];
A[t + 1] = A[i];
A[i] = tt;
}
for(int i = 1; i <= n; i++){
cout << A[i] << " ";
}
}
int main(){
srand(time(0));
ini();
int x = 10;
// xipai(x);
xipai2(x);
return 0;
}