重复嵌套的for循环应该怎么优化代码

时间:2022-09-08 11:33:32
重复嵌套的for循环应该怎么优化代码

这样嵌套的重复代码,有什么方法可以优化吗?

除了for之外,还有什么地方是可以改进优化的吗?

新手一枚,还请大佬们多敲打

8 个解决方案

#1


没懂你的意思,你是想优化for的次数,还是迭代?

#2


这个for循环明显太重复了

#3


百度搜“字典法”

#4


你是要动态的生成排列组合吧!回溯法。
建议你看看这个文章:
https://blog.csdn.net/goldenhawking/article/details/80037669
Pn,m排列、Cnm组合,级联for循环展开,都可以用类似的思路。文章中最后有级联for的例子。

#5



#include <vector>
#include <stdio.h>
struct tag_FOR_State
{
std::vector<unsigned long long> vec_buf;
std::vector<unsigned long long> vec_bz;
int swim;
bool finished;
};

int fnm(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output, tag_FOR_State * state, int limit/* = 0*/)
{
std::vector<unsigned long long> & vec_buf = state->vec_buf,
&vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;

if (vec_bz.size() == 0)
{
for (int i = 0; i<m; ++i)    vec_buf.push_back(0);
vec_bz.push_back(0);
swim = 0;
finished = false;
}

if (finished == true)
return 0;
int group = 0;
do
{
unsigned long long ch = 0;
if (swim<m)
{
vec_buf[swim] = ch;
++swim;
}
if (swim == m)
{
vec_output.push_back(vec_buf);
++group;
bool hit = false;
do
{
--swim;
if (swim >= 0)
{
unsigned long long nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >= n[swim])
break;
hit = true;
} while (hit == false);
if (hit == true)
{
vec_buf[swim] = nextv;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group >= limit && limit>0)
break;
}
} while (finished == false);
return group;
}

int fnm_next(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output, tag_FOR_State * state, int limit/* = 0*/)
{
std::vector<unsigned long long> & vec_buf = state->vec_buf,
&vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;

if (vec_bz.size() == 0)
{
for (int i = 0; i<m; ++i)    vec_buf.push_back(0);
vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished == true)
return 0;
int group = 0;
do
{
unsigned long long ch = 0;
if (swim<m)
{
vec_buf[swim] = ch;
++swim;
}
if (swim == m)
{
memcpy(vec_output[group].data(), vec_buf.data(), m * sizeof(unsigned long long));
++group;
bool hit = false;
do
{
--swim;
if (swim >= 0)
{
unsigned long long nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >= n[swim])
break;
hit = true;
} while (hit == false);
if (hit == true)
{
vec_buf[swim] = nextv;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group >= limit && limit>0)
break;
}
} while (finished == false);
return group;
}

int main()
{
tag_FOR_State state;
const unsigned long long n[] = { 26,26,10,4,10 };
const int m = sizeof(n)/sizeof(n[0]);
std::vector<std::vector<unsigned long long> > vec_res;
int nret = fnm(n, m, vec_res, &state, 1024);
while (nret)
{
for (int i = 0; i < nret; ++i)
printf("%c%c%c%c%c\r",
char(vec_res[i][0] + 'a'),
char(vec_res[i][1] + 'A'),
char(vec_res[i][2] + '!'),
char(vec_res[i][3] + '@'),
char(vec_res[i][4] + '0')
);
nret = fnm_next(n, m, vec_res, &state, 1024);
}
return 0;
}

#6


递归

#include "stdafx.h"
#include <string>
#define LastIndex 3

char a[] = "ddws";
char b[] = "aaaa";
void Next(int index);

int main()
{
Next(0);
return 0;
}

void Next(int index)
{
if (index > LastIndex)
{
if (strcmp(a, b) == 0)
{
printf("密码是%s", b);
}
return;
}
while (b[index] <= 'z')
{
int i = index;
while (++i <= LastIndex)
{
b[i] = 'a';
}
Next(index + 1);
b[index]++;
}
}

#7


这样相当于26进制数的递增吧。
#include <string>
#define LEN 4

void main() {
    char pwd[LEN + 1] = "sdfa";
    char str[LEN + 1] = "aaaa";
    while ( str[LEN] <= 'z' && strcmp( str, pwd ) != 0 ) {
        for ( int i = 0; i < LEN; ++i ) {
            if ( ++str[i] > 'z' ) {
                str[i] = 'a';
            }
            else {
                break;
            }
        }
    }
    printf( "%s\n", str );
    getchar();
}

#8


引用 6 楼 xg436 的回复:
递归

#include "stdafx.h"
#include <string>
#define LastIndex 3

char a[] = "ddws";
char b[] = "aaaa";
void Next(int index);

int main()
{
Next(0);
return 0;
}

void Next(int index)
{
if (index > LastIndex)
{
if (strcmp(a, b) == 0)
{
printf("密码是%s", b);
}
return;
}
while (b[index] <= 'z')
{
int i = index;
while (++i <= LastIndex)
{
b[i] = 'a';
}
Next(index + 1);
b[index]++;
}
}

while (++i <= LastIndex)
这个为什么用while而不用if呢?

#1


没懂你的意思,你是想优化for的次数,还是迭代?

#2


这个for循环明显太重复了

#3


百度搜“字典法”

#4


你是要动态的生成排列组合吧!回溯法。
建议你看看这个文章:
https://blog.csdn.net/goldenhawking/article/details/80037669
Pn,m排列、Cnm组合,级联for循环展开,都可以用类似的思路。文章中最后有级联for的例子。

#5



#include <vector>
#include <stdio.h>
struct tag_FOR_State
{
std::vector<unsigned long long> vec_buf;
std::vector<unsigned long long> vec_bz;
int swim;
bool finished;
};

int fnm(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output, tag_FOR_State * state, int limit/* = 0*/)
{
std::vector<unsigned long long> & vec_buf = state->vec_buf,
&vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;

if (vec_bz.size() == 0)
{
for (int i = 0; i<m; ++i)    vec_buf.push_back(0);
vec_bz.push_back(0);
swim = 0;
finished = false;
}

if (finished == true)
return 0;
int group = 0;
do
{
unsigned long long ch = 0;
if (swim<m)
{
vec_buf[swim] = ch;
++swim;
}
if (swim == m)
{
vec_output.push_back(vec_buf);
++group;
bool hit = false;
do
{
--swim;
if (swim >= 0)
{
unsigned long long nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >= n[swim])
break;
hit = true;
} while (hit == false);
if (hit == true)
{
vec_buf[swim] = nextv;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group >= limit && limit>0)
break;
}
} while (finished == false);
return group;
}

int fnm_next(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output, tag_FOR_State * state, int limit/* = 0*/)
{
std::vector<unsigned long long> & vec_buf = state->vec_buf,
&vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;

if (vec_bz.size() == 0)
{
for (int i = 0; i<m; ++i)    vec_buf.push_back(0);
vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished == true)
return 0;
int group = 0;
do
{
unsigned long long ch = 0;
if (swim<m)
{
vec_buf[swim] = ch;
++swim;
}
if (swim == m)
{
memcpy(vec_output[group].data(), vec_buf.data(), m * sizeof(unsigned long long));
++group;
bool hit = false;
do
{
--swim;
if (swim >= 0)
{
unsigned long long nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >= n[swim])
break;
hit = true;
} while (hit == false);
if (hit == true)
{
vec_buf[swim] = nextv;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group >= limit && limit>0)
break;
}
} while (finished == false);
return group;
}

int main()
{
tag_FOR_State state;
const unsigned long long n[] = { 26,26,10,4,10 };
const int m = sizeof(n)/sizeof(n[0]);
std::vector<std::vector<unsigned long long> > vec_res;
int nret = fnm(n, m, vec_res, &state, 1024);
while (nret)
{
for (int i = 0; i < nret; ++i)
printf("%c%c%c%c%c\r",
char(vec_res[i][0] + 'a'),
char(vec_res[i][1] + 'A'),
char(vec_res[i][2] + '!'),
char(vec_res[i][3] + '@'),
char(vec_res[i][4] + '0')
);
nret = fnm_next(n, m, vec_res, &state, 1024);
}
return 0;
}

#6


递归

#include "stdafx.h"
#include <string>
#define LastIndex 3

char a[] = "ddws";
char b[] = "aaaa";
void Next(int index);

int main()
{
Next(0);
return 0;
}

void Next(int index)
{
if (index > LastIndex)
{
if (strcmp(a, b) == 0)
{
printf("密码是%s", b);
}
return;
}
while (b[index] <= 'z')
{
int i = index;
while (++i <= LastIndex)
{
b[i] = 'a';
}
Next(index + 1);
b[index]++;
}
}

#7


这样相当于26进制数的递增吧。
#include <string>
#define LEN 4

void main() {
    char pwd[LEN + 1] = "sdfa";
    char str[LEN + 1] = "aaaa";
    while ( str[LEN] <= 'z' && strcmp( str, pwd ) != 0 ) {
        for ( int i = 0; i < LEN; ++i ) {
            if ( ++str[i] > 'z' ) {
                str[i] = 'a';
            }
            else {
                break;
            }
        }
    }
    printf( "%s\n", str );
    getchar();
}

#8


引用 6 楼 xg436 的回复:
递归

#include "stdafx.h"
#include <string>
#define LastIndex 3

char a[] = "ddws";
char b[] = "aaaa";
void Next(int index);

int main()
{
Next(0);
return 0;
}

void Next(int index)
{
if (index > LastIndex)
{
if (strcmp(a, b) == 0)
{
printf("密码是%s", b);
}
return;
}
while (b[index] <= 'z')
{
int i = index;
while (++i <= LastIndex)
{
b[i] = 'a';
}
Next(index + 1);
b[index]++;
}
}

while (++i <= LastIndex)
这个为什么用while而不用if呢?