Если мы рассматриваем рекурсивную функцию в C/C++, действительно ли они полезны всегда? Где точно они используются главным образом? Есть ли какие-либо преимущества с точки зрения памяти при помощи рекурсивных функций?
Править: рекурсия лучше или использующий некоторое время цикл?
Попробуйте:
$this->load->database();
echo $this->db->dbprefix;
Обычно вы можете использовать $ this- > config- > предмет но я думаю, что это позволяет только переменные, набор в $ config
-121--3232461-Это, конечно, зависит от того, что делает ваша конкретная среда при загрузке программы; куда помещаются статические данные программы? Во многих операционных системах программа загружается в кучную память и запускается оттуда, так что ваши статические данные все равно окажутся в куче.
-121--4950472-Рекурсивные функции используются в первую очередь для простоты того , чтобы намереваться алгоритмов. Например, вам нужно рекурсивно пересечь дерево каталогов - его глубина ограничена, так что вы, скорее всего, никогда не столкнетесь с чем-то вроде слишком глубокой рекурсии и последующего переполнения стека, но запись рекурсивно скрещивания дерева намного проще, а затем делать то же самое итеративным способом.
В большинстве случаев рекурсивные функции не экономят память по сравнению с итеративными решениями. Еще хуже, что они потребляют память стека, которая является относительно скарзовой.
проверьте состояние порта 5900
-121--2801443-Ознакомьтесь с подробным сравнением элементов управления Telerik для Silverlight и набора инструментов Silverlight.
http://www.telerik.com/products/silverlight/resources/radcontrols-versus-toolkit-comparison.aspx
-121--3505042- При использовании рекурсии можно сохранить данные в стеке (фактически в контекстах вызова всех функций над текущим экземпляром), которые необходимо было бы сохранить в куче с динамическим распределением, если бы вы пытались сделать то же самое с помощью цикла while
.
Подумайте о большинстве алгоритмов «разделяй и побеждай», где есть две вещи, которые нужно сделать для каждого вызова (то есть один из вызовов не является хвостовым рекурсивным).
И что касается интересного комментария/подвопроса Тома, то это преимущество рекурсивных функций, возможно, особенно заметно в C, где управление динамической памятью является таким базовым. Но это не делает его очень специфичным для C.
у них много применений, и без них некоторые вещи становятся очень трудными или невозможными. например, повторяющиеся деревья.
Рекурсивные функции упрощают кодирование решений, имеющих рекуррентное отношение .
Например, функция факториала имеет рекуррентное отношение:
factorial(0) = 1
factorial(n) = n * factorial(n-1)
Ниже я реализовал факториал, используя рекурсию и цикл.
Рекурсивная версия и отношение рекуррентности, определенные выше, выглядят одинаково и поэтому их легче читать.
Рекурсивный:
double factorial ( int n )
{
return ( n ? n * factorial ( n-1 ) : 1 );
}
Цикл:
double factorial ( int n )
{
double result = 1;
while ( n > 1 )
{
result = result * n;
n--;
}
return result;
}
Еще одна вещь:
Рекурсивная версия факториала включает хвостовой вызов самого себя и может быть оптимизирована по хвостовому вызову. Это сводит пространственную сложность рекурсивного факториала к пространственной сложности итеративного факториала.
Используйте:
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
. После этого форма помещается на панель задач.
-121--949009-Можно использовать netstat для проверки наличия установленного подключения к порту, который прослушивает сервер VNC.
попробуйте netstat -an | найти «ESTABLISHED» | найти «: 5900»
в Windows в командной строке.
Если кто-то подключен, для него появится запись строки.
Примечание. Если вы подключаетесь к другому серверу, то этот поиск также обнаружит это подключение, поэтому обратите внимание на наличие : 5900
во втором столбце слева, так как это локальный компьютер.
Есть две причины, которые я вижу для использования рекурсии:
Обрабатывать рекурсию с осторожностью, так как всегда существует опасность бесконечной рекурсии.
Внедрите QuickSort с рекурсией и без нее, тогда вы сможете сами определить, полезно это или нет.
Я часто найти рекурсивные алгоритмы легче для понимания, потому что они включают менее изменчивое состояние. Рассмотрим алгоритм определения наибольшего общего делителя двух чисел.
unsigned greatest_common_divisor_iter(unsigned x, unsigned y)
{
while (y != 0)
{
unsigned temp = x % y;
x = y;
y = temp;
}
return x;
}
unsigned greatest_common_divisor(unsigned x, unsigned y)
{
return y == 0 ? x : greatest_common_divisor(y, x % y);
}
На мой вкус, в итеративной версии происходит слишком много переименований. В рекурсивной версии все неизменяемо, поэтому вы даже можете сделать x и y const
, если хотите.
Рекурсия определенно имеет преимущества при задачах с рекурсивной природой. Другие плакаты называли некоторых из них.
Однозначное использование возможностей C для рекурсии имеет преимущества в управлении памятью. Когда вы пытаетесь избежать рекурсии, большую часть времени для решения проблемы используется собственный стек или другой динамический тип данных. Это включает управление динамической памятью в C / C ++. Динамическое управление памятью дорого и подвержено ошибкам!
Вы не можете превзойти стек
С другой стороны, когда вы просто используете стек и используете рекурсию с локальными переменными - управление памятью просто, а стек в большинстве случаев более эффективен по времени затем все управление памятью вы можете сделать самостоятельно или с помощью простого управления памятью C / C ++. Причина в том, что системный стек представляет собой такую простую и удобную структуру данных с низкими накладными расходами и реализуется с использованием специальных операций процессора, оптимизированных для этой работы. Поверьте, вы не сможете превзойти это, поскольку компиляторы, операционные системы и процессоры оптимизированы для манипуляций со стеком на протяжении десятилетий!
PS: Также стек не становится фрагментированным, в отличие от кучи памяти. Таким образом также можно сэкономить память, используя стек / рекурсию.
Этот трюк по вызову частных методов с помощью Delegate.CreateDelegate чрезвычайно аккуратен.
var subject = new Subject();
var doSomething = (Func<String, String>)
Delegate.CreateDelegate(typeof(Func<String, String>), subject, "DoSomething");
Console.WriteLine(doSomething("Hello Freggles"));
-121--1749454- Это работает:
map.resource :post, :collection => { :my_action => :get}
-121--128791- Динамическое программирование - это ключевая область, где рекурсия имеет решающее значение, хотя она выходит за рамки этого (запоминание дополнительных ответов может дать резкие улучшения производительности). Алгоритмы - это те, где обычно используется рекурсия, а не обычное кодирование день в день. Это скорее компьютерная научная концепция, чем программная.
Стоит упомянуть, что на большинстве функциональных языков (например, на схеме) вы можете воспользоваться преимуществами оптимизации хвостового вызова и, таким образом, вы можете использовать рекурсивные функции без увеличения объем памяти в вашем стеке.
По сути, сложные рекурсивные хвостовые вызовы могут безупречно выполняться в Scheme, тогда как в C / C ++ те же самые вызовы вызовут переполнение стека.