Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Рекурсивная функция 
:(
    Опции темы
observateur
Дата 10.6.2006, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 10.6.2006

Репутация: нет
Всего: нет



Заранее спасибо тем кто ответить...Самостоятолна изучаю C++. помогите пожалоста  понять как работает Рекурсивная функция. Уменя есть книга Х.М.Дейтель "Как программировать на С++". Все равно трудно понять суть рекурсии. smile  
PM MAIL   Вверх
Xenon
Дата 10.6.2006, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Что значит КАК? Ну функция из самой себя вызывает саму себя с новым аргументом smile Удобно использовать для математических вычислений, в конце концов для вычисления факториала smile Единственное, нужно следить, чтобы проверялось условие и этот цикл завершился когда-нибудь, а не стал бесконечным smile
Вот нахождение факториала простым способом
Код

int fact(int n)
{
    int result=1;
    for (int i=1;i<=n;i++) 
    {
        result=result*i;
    }
    return result;


Вот пр помощи рекрусси:
Код

int fact(int n)
{
    if (n==1) // факториал единицы равен одному
    {
        return 1;
    }
    else           
    {
        return n*fact(n-1);
    }
}  
  

Это сообщение отредактировал(а) XenonSk - 10.6.2006, 12:58


--------------------
user posted image  
PM MAIL   Вверх
observateur
Дата 10.6.2006, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 10.6.2006

Репутация: нет
Всего: нет



Я знаю условия цикла рекурсивный функции. мне надо схема ее рабаты. Точнее схематический как она работает. спасибо за вашу терпению 
PM MAIL   Вверх
AlanG
Дата 10.6.2006, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 11.5.2006
Где: РашЫн ФидирейшЫн

Репутация: нет
Всего: нет



Цитата

Я знаю условия цикла рекурсивный функции. мне надо схема ее рабаты. Точнее схематический как она работает. спасибо за вашу терпению  

Так все спрашивают, когда начинаю smile . Это не нужно, и вообще задумыватся над этим не надо, поверь smile . Логика проста, как два мегабайта скачать smile 
А думать о схеме не надо, вот как это происходит



Код

int fact(int n)
{
    if (n==1) // факториал единицы равен одному
    {
        return 1;
    }
    else           
    {
        return n*fact(n-1); //сдесь fact(n-1) - это вызов функции fact(), причем заметь что ему (функции fact) 
//передается агрумент в виде числа равного (n-1) и все, вся рекурсия
 //А то что return (возврат), он сразу не происходит, сначала всеже вызывается 
//функция, а вот когда n cтанет равным 1, последнему вызову возвратится результат, 
//этот результат перемножается с n (n*fact(n-1))
 
    }



Вообще все вызовы сохраняются в стеке, и каждому вызову присваивается значение с помощбю return
  

Это сообщение отредактировал(а) AlanG - 10.6.2006, 13:28
PM MAIL   Вверх
Pete
Дата 10.6.2006, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



XenonSk, 0! = 1.
Код
int fact (int n) {
  if (n == 0) return 1;
  return (n * fact (n - 1));
}


На примере того же факториала:
Мы знаем рекуррентное соотношение (которое, кстати, лежит в основе каждой рекурсивной функции):
fact (n) = n * fact (n - 1).
Вот мы это и реализуем: в предположении, что наша функция вычисляет факториал, пишем, что "n! = n(n - 1)!".
При этом мы уверены, что (n - 1)! будет вычислен правильно. На основе этого получаем то, что надо.     

Это сообщение отредактировал(а) Pete - 10.6.2006, 14:26


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
AlanG
Дата 10.6.2006, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 11.5.2006
Где: РашЫн ФидирейшЫн

Репутация: нет
Всего: нет



Цитата

XenonSk, 0! = 1.

А ноль для интереса прибавил, или чтобы начинающего запутать smile 

Цитата

На примере того же факториала:
Мы знаем рекуррентное соотношение (которое, кстати, лежит в основе каждой рекурсивной функции):
fact (n) = n * fact (n - 1).
Вот мы это и реализуем: в предположении, что наша функция вычисляет факториал, пишем, что "n! = n(n - 1)!".
При этом мы уверены, что f (n - 1). На основе этого получаем то, что надо.  

Перевод будет? smile 

 
PM MAIL   Вверх
Xenon
Дата 10.6.2006, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Pete, Ну и? smile 


--------------------
user posted image  
PM MAIL   Вверх
Pete
Дата 10.6.2006, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



Поправил) 


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
Xenon
Дата 10.6.2006, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Млин, я 0!=1 прочитал, как : "Нуль не равен единице" ...  smile  
Тогда уж:
Код

int fact(int n)    
{    
    if (n==0 || n==1)  
    {    
        return 1;    
    }    
    else            
    {    
        return n*fact(n-1);    
    }    
}  
  

Это сообщение отредактировал(а) XenonSk - 10.6.2006, 14:32


--------------------
user posted image  
PM MAIL   Вверх
Pete
Дата 10.6.2006, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



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


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
observateur
Дата 10.6.2006, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 10.6.2006

Репутация: нет
Всего: нет



Спасибо всем кто отвечал. Постараюс понять. 
PM MAIL   Вверх
MAKCim
Дата 10.6.2006, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

и выйгрыша почти никакого.  

я бы сказал вообще никакого  smile  


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Void
Дата 10.6.2006, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(Pete @  10.6.2006,  16:37 Найти цитируемый пост)
сли говорить бо оптимизации, то вычисление факториала с помощью рекурсии гораздо дороже итеративного варианта и выйгрыша почти никакого.  

Хвостовая рекурсия эквивалентна итерации (точнее, наоборот). В приведенном коде рекурсия не хвостовая, но легко к ней сводится. Так что разница в способе вычисления тут скорее не алгоритмическая, и все зависит от прозорливости оптимизатора smile По крайней мере, явную хвостовую рекурсию приличные компиляторы C++ сворачивают уже давно. 


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Pete
Дата 10.6.2006, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



Цитата(MAKCim @  10.6.2006,  17:27 Найти цитируемый пост)
я бы сказал вообще никакого

Небольшой есть.
Цитата(Void @  10.6.2006,  17:45 Найти цитируемый пост)
Хвостовая рекурсия эквивалентна итерации (точнее, наоборот).

Время работы рекурсивной программы никогда не будет эквивалентно ее итерационной версии (именно с прикладной точки зрения), ибо сам процесс вызова функции очень дорог, не говоря уж об ограниченности стека и т.п. А если компилятор умеет распознать рекурсию, то это исключительно его достоинство, а не достоинство метода. Тем более, один это дело оптимизирует, а другой --- нет. На такие вещи, по-моему, нельзя надеяться.  

Это сообщение отредактировал(а) Pete - 10.6.2006, 18:07


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
Void
Дата 10.6.2006, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(Pete @  10.6.2006,  20:07 Найти цитируемый пост)
Время работы рекурсивной программы никогда не будет эквивалентно ее итерационной версии (именно с прикладной точки зрения), ибо сам процесс вызова функции очень дорог, не говоря уж об ограниченности стека и т.п.

Есть алгоритмы, которые рекурсивны по своей природе, и для их итеративной реализации придется организовывать собственный стек. Сомнительный выигрыш.
Цитата(Pete @  10.6.2006,  20:07 Найти цитируемый пост)
На такие вещи, по-моему, нельзя надеяться.  

В С++ — нельзя, согласен.
 


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Pete
Дата 10.6.2006, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



Цитата(Void @  10.6.2006,  18:11 Найти цитируемый пост)
Есть алгоритмы, которые рекурсивны по своей природе, и для их итеративной реализации придется организовывать собственный стек.

Скажем так: любой рекурсивный алгоритм из Кормена, насколько я их помню, можно переписать в итерационном виде с увеличением быстродействия. Если ты имеешь в виду что-то, быть может, экзотическое, то прошу в студию.
 smile  


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
Void
Дата 10.6.2006, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Pete, ничего экзотического, перепиши обычную быструю сортировку (Хоара), не создавая собственного стека.
И сравни быстродействие эмуляции стека с явной рекурсией. Такой вариант, возможно, окажется быстрее, но ненамного. И даже в этом я не уверен. 

Это сообщение отредактировал(а) Void - 10.6.2006, 18:23


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Pete
Дата 10.6.2006, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



Хм.. Согласен. Пока не встречал ее итерационной реализации без стека. Сравнение этих алгоритмов в скорости, наверное, уже больше зависит от системы. Конечно, отсутствие объявления новых переменных на каждом уровне рекурсии придаст определенное ускорение, хотя, кто знает...
(ЗЫ: мы пока от темы не ушли далеко? smile )  

Это сообщение отредактировал(а) Pete - 10.6.2006, 18:45


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
Xenon
Дата 10.6.2006, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Ну мне кажется тут такой же "большой" прирост в скорости, что и при использовании
Код
 
int x=5;
x=x<<1;

Вместо
Код

int x=5;
x*=2
 


--------------------
user posted image  
PM MAIL   Вверх
kirjanov
Дата 10.6.2006, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

Репутация: 1
Всего: 15



XenonSk
конечно, прирост производительности явно не будет большим. Может твой компилятор и сгенерирует эквивалентный код, как в верхней инструкции. Что может быть более показательным сейчас, как использование интерпретируемых языков.... 
PM MAIL   Вверх
Xenon
Дата 10.6.2006, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



kirjanov, То, что кинул я считается не одним и тем же ... Вообще говорят, что часто побитовый сдвиг дает хороший прирост smile 


--------------------
user posted image  
PM MAIL   Вверх
Void
Дата 10.6.2006, 23:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(XenonSk @  11.6.2006,  00:34 Найти цитируемый пост)
Вообще говорят, что часто побитовый сдвиг дает хороший прирост 

Я не знаю компилятора, настолько тупого, чтобы умножение или деление на константу он не превратил в битовый сдвиг.
И, кстати, в случае знакововых чисел можно сильно огрести, использовав сдвиг вправо вместо деления:
Код
#include <cstdio>
#include <cstdlib>

int main() {
    int x = -1;
    printf("%i %i", x >> 1, x / 2);
}

Цитата
-1 0


И еще:
Код
#include <cstdio>
#include <cstdlib>

int main() {
    int x = rand();
    int y = rand();
    x <<= 1;
    y *= 2;
    printf("%i %i", x, y);
}

Код
;;;    int x = rand();
        call      _rand                                         ;5.10
$B1$8:
        mov       ebx, eax                                      ;5.10
$B1$2:
;;;    int y = rand();
        call      _rand                                         ;6.10
$B1$3:
;;;    x <<= 1;
        add       ebx, ebx                                      ;7.2
;;;    y *= 2;
        add       eax, eax                                      ;8.2

Это Intel C++ 9.0 в режиме максимальной оптимизации.
Не оптимизируйте, и не оптимизируемы будете smile 


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Xenon
Дата 10.6.2006, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Void, просто говорю, что в справочнике написано, а об "вылезании" там тоже писали smile 


--------------------
user posted image  
PM MAIL   Вверх
MAKCim
Дата 11.6.2006, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

ничего экзотического, перепиши обычную быструю сортировку (Хоара), не создавая собственного стека.
И сравни быстродействие эмуляции стека с явной рекурсией. Такой вариант, возможно, окажется быстрее, но ненамного. И даже в этом я не уверен. 

думаю вариант с эмуляцией будет быстрее
насколько я знаю при рекурсивном вызове в стек заносится все окружение (локальные переменные) и адрес возврата
при эмуляции заносятся лишь необходимые данные
при быстрой организации нашего стека (например статический массив) думаю он будет по-эффективнее явной рекурсии 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Void
Дата 11.6.2006, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(MAKCim @  11.6.2006,  11:45 Найти цитируемый пост)
насколько я знаю при рекурсивном вызове в стек заносится все окружение (локальные переменные) и адрес возврата

В стек заносится лишь адрес возврата и параметры вызываемой функции.
Да, вызываемая функция выделяет место на стеке для своих локальных переменных, но это — одна инструкция изменения регистра стека.
Цитата(MAKCim @  11.6.2006,  11:45 Найти цитируемый пост)
при быстрой организации нашего стека (например статический массив)

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


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
MAKCim
Дата 12.6.2006, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

В стек заносится лишь адрес возврата и параметры вызываемой функции.

я это и имел в виду, не так выразился
Цитата

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

под статическим массивом я подразумевал массив на стеке (размер известен в compile-time)
как пример можно взять рекурсивную функцию
Код

void F(int a)
{
    if (a==63) return;
    F(a+1);
    std::cout<<a<<std::endl;
}

и эквивалентную ее итеративную с эмуляцией стека
Код

void G(int a)
{
    int stack[63];
    char index=0;
    while (index!=63)
    {
        stack[index]=a;
        ++index;
        ++a;
    }
    while (--index) std::cout<<stack[index]<<std::endl;
    std::cout<<stack[index]<<std::endl;
}

и вызов
Код

int main()
{
    F(0);
    G(0);
    return 0;
}

тут итеративная выигрывает в используемой памяти (261 против 512 байт) и по количеству команд процессора
(326 против 575 (вывод считаем оной командой; командную реализацию while и if не рассматриваем))
так как любая рекурсивная программа сводится к итеративной, то, как показывает пример, при правильной ее организации она оказывается более эффективной  

Это сообщение отредактировал(а) MAKCim - 12.6.2006, 09:42


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Void
Дата 14.6.2006, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Эх, люблю я бенчмарки проводить smile Вот и в этот раз не выдержал и написал тест. Все ту же быструю сортировку в двух вариантах: явная рекурсия и эмуляция через стек.
Код
#include <iostream>
#include <algorithm>
#include <functional>
#include <utility>
#include <vector>
#include <climits>
#include <cstdlib>
#include <ctime>


// Возвращает медиану из первого, последнего и серединного элемента.
template <typename Iterator, typename Comparer>
inline Iterator find_pivot(Iterator begin, Iterator end,
                           const Comparer &cmp) {
    Iterator middle = begin + (end - begin) / 2;
    if (cmp(*begin, *middle) && cmp(*(end - 1), *begin)
        || !cmp(*begin, *middle) && !cmp(*(end - 1), *begin))
        return begin;
    else if (cmp(*(end - 1), *middle) && cmp(*begin, *(end - 1))
        || !cmp(*(end - 1), *middle) && !cmp(*begin, *(end - 1)))
        return end - 1;
    return middle;
}

template <typename Iterator, typename Comparer>
inline Iterator partition(Iterator begin, Iterator end, Iterator pivot,
                          const Comparer &cmp) {
    typename std::iterator_traits<Iterator>::value_type pivotValue(*pivot);
    std::iter_swap(pivot, end - 1);
    Iterator p = std::partition(begin, end - 1, std::bind2nd(cmp, pivotValue));
    iter_swap(p, end - 1);
    return p;
}

template <typename Iterator, typename Comparer>
void rec_qsort(Iterator begin, Iterator end,
               const Comparer &cmp = Comparer()) {
    if (end - begin > 1) {
        Iterator pivot = find_pivot(begin, end, cmp);
        pivot = partition(begin, end, pivot, cmp);
        if (pivot - begin > end - pivot) {
            rec_qsort(begin, pivot, cmp);
            rec_qsort(pivot + 1, end, cmp);
        } else {
            rec_qsort(pivot + 1, end, cmp);
            rec_qsort(begin, pivot, cmp);
        }
    }
}

template <typename Iterator>
void rec_qsort(Iterator begin, Iterator end) {
    rec_qsort(begin, end,
        std::less<typename std::iterator_traits<Iterator>::value_type>());
}

template <typename Iterator, typename Comparer>
void qsort(Iterator begin, Iterator end, const Comparer &cmp = Comparer()) {
    // глубина рекурсии не превышает log_2(n), где n - длина сортируемой
    // последовательности
    std::pair<Iterator, Iterator> stack[
        sizeof(typename std::iterator_traits<Iterator>::difference_type) *
        CHAR_BIT];
    size_t top = 0;
    stack[top++] = std::make_pair(begin, end);
    while (top) {
        --top;
        begin = stack[top].first;
        end = stack[top].second;
        while (end - begin > 1) {
            Iterator pivot = find_pivot(begin, end, cmp);
            pivot = partition(begin, end, pivot, cmp);
            if (pivot - begin > end - pivot) {
                stack[top++] = std::make_pair(begin, pivot);
                begin = pivot + 1;
            } else {
                stack[top++] = std::make_pair(pivot + 1, end);
                end = pivot;
            }
        }
    }
}

template <typename Iterator>
void qsort(Iterator begin, Iterator end) {
    qsort(begin, end,
        std::less<typename std::iterator_traits<Iterator>::value_type>());
}


class timer {
    clock_t start_;
public:
    timer() : start_(clock()) { }

    double elapsed() {
        return 1.0 * (clock() - start_) / CLOCKS_PER_SEC;
    }

    void reset() {
        start_ = clock();
    }
};


int myrandom() {
    return rand() * (RAND_MAX + 1) + rand();
}


int main() {
    const size_t arraySize = 40000000;

    srand(time(NULL));
    std::vector<int> a(arraySize), b;
    std::generate(a.begin(), a.end(), myrandom);
    b = a;
    
    timer t;
    rec_qsort(a.begin(), a.end());
    std::cout << "Recursion:\t" << t.elapsed() << " sec" << std::endl;
    
    t.reset();
    qsort(b.begin(), b.end());
    std::cout << "No recursion:\t" << t.elapsed() << " sec" << std::endl;
}

Результаты:
GCC 3.4.5 (MinGW)
Цитата
Recursion:      7.797 sec
No recursion:   7.781 sec

Recursion:      7.797 sec
No recursion:   7.766 sec

Recursion:      7.812 sec
No recursion:   7.782 sec

Recursion:      7.797 sec
No recursion:   7.781 sec

Recursion:      7.797 sec
No recursion:   7.859 sec

VC 8.0:
Цитата
Recursion:      8.61 sec
No recursion:   8.719 sec

Recursion:      8.656 sec
No recursion:   8.766 sec

Recursion:      8.625 sec
No recursion:   8.781 sec

Recursion:      8.61 sec
No recursion:   8.765 sec

Recursion:      8.656 sec
No recursion:   8.735 sec

Вот такая забавная картина, не находите? smile
Так стоит ли заморачиваться с ручной эмуляцией стека ради пары процентов производительности, которые в зависимости от компилятора могут оказаться и на той, и на другой стороне? ИМХО, нет.
В данном случае можно было оценить верхний предел глубины рекурсии, однако выделяя под стек массив постоянного размера мы в любом случае рискуем молчаливо вылететь за его пределы. Используя же динамический массив мы рискуем свести на нет все призрачные преимущества эмуляции рекурсии. 


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1285 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.