2016-09-12 3 views
3

Я новичок в C++, но думал, что работа над некоторыми проблемами проекта Euler ознакомит меня с языком.Переполнение стека рекурсии C++

При попытке Project Euler Problem 14: Longest Collatz sequence

мне не удалось получить мои C++ решения работать, но не было никаких проблем с моим питоном решением ...

import time 
start = time.time() 
memo = {1:1,2:2} 
longest_chain, longest_starting_key = 2, 2 

def rec(a): 
    global longest_chain, longest_starting_key 

    if a in memo.keys(): 
     return memo[a]  
    if a % 2 == 0: 
     memo[a] = rec(a // 2) + 1 
    else: 
     memo[a] = rec(3 * a + 1) + 1 
    if memo[a] > longest_chain: 
     longest_chain = memo[a] 
     longest_starting_key = a 
    return memo[a]  

for i in range(1000000,3,-1): rec(i) 

print("starting key", longest_starting_key , ": has length", longest_chain) 
print((time.time() - start), "seconds") 

и получил

starting key 837799 has length 525 
1.399820327758789 seconds 

Моя попытка C++ ... (что я считал эквивалентной ...)

#include <iostream> 
#include <unordered_map> 
std::unordered_map<int, int> mem = { {1,1},{2,2} }; 
int longest_chain{ 2 }, best_starting_num{ 2 }; 

bool is_in(const int& i){ 
    auto search = mem.find(i); 
    if(search == mem.end()) 
     return false; 
    else 
     return true; 
} 

int f(int n){ 
    if(is_in(n)) 
     return mem[n]; 
    if(n % 2) 
     mem[n] = f(3 * n + 1) + 1; 
    else 
     mem[n] = f(n/2) + 1; 
    if(mem[n] > longest_chain) 
     longest_chain = mem[n]; 
    return mem[n]; 
} 

int main(){ 
    for(int i = 3; i < 1000000; i++){ 
     f(i); 
    } 
    std::cout << longest_chain << std::endl; 
} 

При запуске этого в Visual Studio в режиме отладки я получаю следующее сообщение об ошибке

Unhandled exception at 0x00007FF75A64EB70 in 
0014_longest)collatz_sequence_cpp.exe: 0xC00000FD: Stack overflow 
(parameters: 0x0000000000000001, 0x000000DC81493FE0). 

Кто-то сказал мне, что я должен выделить в куче с помощью указателей, но имеют очень ограниченный опыт работы с указателями .. .

Другая вещь, которую я не понимаю, - это когда я запускаю ее с 100'000 вместо 1'000'000 в петле основного тела, она работает, но очень медленная.

+0

запуск его через vC++ отладчик поможет много. Я думаю, что 'mem' уже выделяет новые элементы в куче. –

+1

Когда я запускаю свой код на C++ в своей системе, я получаю результат из 489 (не 525). Варианты Python и C++ явно не эквивалентны ... –

+1

@Barry ниже дает очень хороший алгоритмический ответ, но в вашей версии C++ также есть ошибка кодирования - вы выполняете поиск по карте дважды, когда присутствует значение, сначала для обнаружения доступность, вторая, чтобы получить его. Нехорошо. – SergeyA

ответ

5

Подсказка: Что такое инвариант на интервале n, что последовательность Коллатца обеспечивает (математически), что ваш код Python удовлетворяет, но ваш код C++ не делает? Подсказка к подсказке: каковы последние несколько значений n перед переполнением стека?

+0

А, вот что я собирался сказать, но формат подсказок в большей степени соответствует образовательной теме контекста вопроса. :) – wally

+0

Я смотрю на это, но безрезультатно. Я изменил основной цикл в версии python, чтобы он выглядел как версия C++ (вместо того, чтобы подсчитывать значение от 1 до 999'999). изменили имена, чтобы они больше походили друг на друга ... Но я все еще не могу это понять. – Quantifeye

+1

@ Quantifeye Начало в '113383'. Каковы все значения 'n', которые вы называете' f'? – Barry

 Смежные вопросы

  • Нет связанных вопросов^_^