Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сортировка через стек

6.6K
18 сентября 2008 года
Mendler
48 / / 20.09.2006
есть у кавонить алгоритм быстрой сортировки стека?
P.S. Не используя массивы и другие структуры данных, только стек, первоначальные данные вводятся в стек из файла.
14
19 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
ну у Кнута должен быть
5
19 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: Mendler
P.S. Не используя массивы и другие структуры данных, только стек, первоначальные данные вводятся в стек из файла.

Без использования дополнительных структур данных - невозможно.

Подозреваю, что нужно использовать "аппаратный" стек вызовов?

6.6K
19 сентября 2008 года
Mendler
48 / / 20.09.2006
Необходимо использовать только команды Push, Pop, Top, IsEmpty :)
5
19 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: Mendler
Необходимо использовать только команды Push, Pop, Top, IsEmpty :)

Хорошая задача.
Если хватит соображалки, то с C# переведете:

Код:
using System;
using System.Collections.Generic;
using System.Text;

namespace StackSort {
    class Program {

        static void SortCompareAndPush<T>(Stack<T> stack, ref T item)
            where T: IComparable<T> {
            if (stack.Count > 0) {    // if(!stack.IsEmpty) {
                do {
                    T next_item = stack.Pop();
                    if (item.CompareTo(next_item) == 1) {   // if(item > next_item) {
                        T temp = item;
                        item = next_item;
                        next_item = temp;
                    }
                    SortCompareAndPush<T>(stack, ref next_item);
                } while (item.CompareTo(stack.Peek()) == 1);  // } while(item > stack.Top);
            }
            stack.Push(item);
        }

        static void SortStack<T>(Stack<T> stack)
            where T : IComparable<T> {
            if (stack.Count > 1) {     // if(!stack.IsEmpty) {
                T item = stack.Pop();
                SortCompareAndPush<T>(stack, ref item);
            }
        }

        static void PrintStack<T>(Stack<T> stack) {
            foreach (T item in stack) {
                Console.WriteLine(item);
            }
        }

        static void Main(string[] args) {
            Stack<int> stack = new Stack<int>();

            Random rnd = new Random();
            for (int i = 0; i < 20; ++i)
                stack.Push(rnd.Next(100));

            Console.WriteLine("Initial stack:");
            PrintStack<int>(stack);

            SortStack<int>(stack);

            Console.WriteLine("Sorted stack:");
            PrintStack<int>(stack);

            Console.ReadKey();
        }
    }
}
Код сортирует универсальный стек (класс Stack<T>) с использованием только лишь рекурсии.
Модификатор ref перед параметрами означает передачу аргумента по ссылке. Аналог & в C/C++ и var в Pascal.

З.Ы. Временная сложность сортировки в худшем случае O(n ^ 2).
41K
21 сентября 2008 года
Lenujkee
7 / / 21.09.2008
А теперь вся фишка...)) нужно сделать тоже тока для 50000 элементов...переполнение возникает:\Подскажи,плиз, как обойти?
5
21 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: Lenujkee
А теперь вся фишка...)) нужно сделать тоже тока для 50000 элементов...переполнение возникает:\Подскажи,плиз, как обойти?

Купить квантовый компьютер. :D
Если вам ничего не говорит временная сложность алгоритма O(n ^ 2), где n = 50000, то вам прямая дорога идти учить матчасть.
Кроме того, глубина рекурсии будет равна количеству элементов в стеке. Секем? А это 50 000 вызовов. В CLR с дефолтным стеком такая рекурсия вызовет переполнение стека.

842
21 сентября 2008 года
sigmov
301 / / 16.09.2008
Код на C++
Все уже написано до нас :)

 
Код:
#include "stdafx.h"
#include <stack>
#include <algorithm>
void main(){
    stack<int> st;
    //Заполнить стэк
    sort(st.c.begin(),st.c.end());//Сортировка
};
массив<int> из 10000 сортировал 2 сек.
5
21 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: sigmov
Код на C++
Все уже написано до нас :)

Дык, быстрая сортировка. Я тоже мог Array.Sort() вызвать.
Изначально задача была - без использования доп средств - структур данных, алгоритмов и прочего. Только операторы стека и рекурсия.

41K
21 сентября 2008 года
Lenujkee
7 / / 21.09.2008
Цитата:
Купить квантовый компьютер. :D
Если вам ничего не говорит временная сложность алгоритма O(n ^ 2), где n = 50000, то вам прямая дорога идти учить матчасть.
Кроме того, глубина рекурсии будет равна количеству элементов в стеке. Секем? А это 50 000 вызовов. В CLR с дефолтным стеком такая рекурсия вызовет переполнение стека.



пошла.. учить мат часть8{

842
21 сентября 2008 года
sigmov
301 / / 16.09.2008
Цитата: hardcase
Дык, быстрая сортировка. Я тоже мог Array.Sort() вызвать.
Изначально задача была - без использования доп средств - структур данных, алгоритмов и прочего. Только операторы стека и рекурсия.


Алгоритм - это не массив и не структура данных. Что сказано в первоначальных условиях.

Lenujkee, не торопитесь учить матчасть.
Стек позволяет получить доступ к iму элементу операцией *(st.c.begin()+i).
Реализуйте алгоритм допустим всплытия, используя данное свойство.
Или это тоже против правил?

5
21 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: sigmov
Алгоритм - это не массив и не структура данных. Что сказано в первоначальных условиях.

Lenujkee, не торопитесь учить матчасть.
Стек позволяет получить доступ к iму элементу операцией *(st.c.begin()+i).
Реализуйте алгоритм допустим всплытия, используя данное свойство.
Или это тоже против правил?

Стек в классике - как тому учат в университетах - не позволяет обращаться в i-му элементу, так как стек, формально, не поддерживает оператор индексации.


А как вы думаете, работает мой пример? Это простейший рекурсивный пузырек, протаскивающий каждый элемент на свое место через стек.

842
21 сентября 2008 года
sigmov
301 / / 16.09.2008
Цитата: hardcase
Стек в классике - как тому учат в университетах - не позволяет обращаться в i-му элементу, так как стек, формально, не поддерживает оператор индексации.

А как вы думаете, работает мой пример? Это простейший рекурсивный пузырек, протаскивающий каждый элемент на свое место через стек.



Согласен с вами. В классике стек именно то, что вы сказали.
Правда сортировать через стек - все равно, что вычерпывать воду из лодки пипеткой, а не ковшом.

Предлагаю свой метод:

Код:
int buf;
    stack<int> st1;
    stack<int> st2;
    stack<int> st_final;
   
    //Заполнить st1//
   
    while(true){
        if(st1.empty()&&st2.empty()) break;
        buf=st1.top();
        st1.pop();
        while(!st1.empty()){
            st2.push(min(buf,st1.top()));
            buf=max(buf,st1.top());
            st1.pop();
        }
        st_final.push(buf);
        if(st1.empty()&&st2.empty()) break;
        buf=st2.top();
        st2.pop();
        while(!st2.empty()){
            st1.push(min(buf,st2.top()));
            buf=max(buf,st2.top());
            st2.pop();
        }
        st_final.push(buf);
    };

    while(!st_final.empty()){
        cout<<st_final.top()<<endl;
        st_final.pop();
    }
842
21 сентября 2008 года
sigmov
301 / / 16.09.2008
Цитата: sigmov
Согласен с вами. В классике стек именно то, что вы сказали.
Правда сортировать через стек - все равно, что вычерпывать воду из лодки пипеткой, а не ковшом.

Предлагаю свой метод:
Код:
int buf;
    stack<int> st1;
    stack<int> st2;
    stack<int> st_final;
   
    //Заполнить st1//
   
    while(true){
        if(st1.empty()&&st2.empty()) break;
        buf=st1.top();
        st1.pop();
        while(!st1.empty()){
            st2.push(min(buf,st1.top()));
            buf=max(buf,st1.top());
            st1.pop();
        }
        st_final.push(buf);
        if(st1.empty()&&st2.empty()) break;
        buf=st2.top();
        st2.pop();
        while(!st2.empty()){
            st1.push(min(buf,st2.top()));
            buf=max(buf,st2.top());
            st2.pop();
        }
        st_final.push(buf);
    };

    while(!st_final.empty()){
        cout<<st_final.top()<<endl;
        st_final.pop();
    }



Его существенный плюс - на каждом шаге число прогоняемых элементов уменьшается на 1.
По моим подсчетам 50000 будет отсортировано за 4-5 часов.

41K
21 сентября 2008 года
Lenujkee
7 / / 21.09.2008
Вот кстати для 50 000 элементов... в принципе же можно разделить один стек на 10(допустим в первый элементы до 5000 во второй от 5000 до 1000и тд) и каждый упорядочить как писал уважаемый hardcase. Отсюда вопрос тогда...В дев с++ можно обьявить около 9 стеков а в вижуале и того меньше штук 7. Может кто нибудь знает как можно увеличить размер памяти занимаемое программой...или количество стеков??Оо заранее спасибо за ответ
41K
21 сентября 2008 года
Lenujkee
7 / / 21.09.2008
Цитата:
По моим подсчетам 50000 будет отсортировано за 4-5 часов.


мммм беда в том что за секунду надо..Это массив простите?? А если списочные элементы?:DDD

5
22 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: Lenujkee
мммм беда в том что за секунду надо..Это массив простите?? А если списочные элементы?:DDD

Сортировать 50 000 элементов менее чем за секунду - это уж простите, нужно квиксортом по массиву утюжить. А не всякие там стеки придумывать.

41K
22 сентября 2008 года
Lenujkee
7 / / 21.09.2008
Цитата:
Сортировать 50 000 элементов менее чем за секунду - это уж простите, нужно квиксортом по массиву утюжить. А не всякие там стеки придумывать.


Ммм, но это ж задали =>выполнимое задание...Тока низнаю как ешо... сейчас таким методом, как у меня выше описано с использованием указателей и 5 стеков перебирает массив за 19 секунд(естественно числа а не списки)...вот еслиб был способ увеличить количество стеков%)

842
22 сентября 2008 года
sigmov
301 / / 16.09.2008
Цитата: Lenujkee
Ммм, но это ж задали =>выполнимое задание...Тока низнаю как ешо... сейчас таким методом, как у меня выше описано с использованием указателей и 5 стеков перебирает массив за 19 секунд(естественно числа а не списки)...вот еслиб был способ увеличить количество стеков%)


Весьма выполнимое, если Oksford'ский Mainframe совместно со Стендсфордским запустить.:D

41K
22 сентября 2008 года
Lenujkee
7 / / 21.09.2008
Цитата:
Весьма выполнимое, если Oksford'ский Mainframe совместно со Стендсфордским запустить.:D


Остроумно, но печально:(

6.6K
09 октября 2008 года
Mendler
48 / / 20.09.2006
Написал сортировку, чем то похожую на квиксорт:
Код:
template <typename TElement>
int sort_stack(TStackMass<TElement> *stk, TStackMass<TElement> *stk1, TStackMass<TElement> *stk2, TStackMass<TElement> *fin)
{
    TElement tmp;
    int min = 0;
    int max = 0;
    tmp = stk->Top();
    while( !stk->IsEmpty() )
    {
        if( tmp <= stk->Top() )
        {
            stk1->Push(stk->Pop());
            max++;
        }
        else
        {
            stk2->Push(stk->Pop());
            min++;
        }
    }
    if( max == 1 )
        fin->Push(stk1->Pop());
    if( max > 1 )
        sort_stack(stk1, stk, stk2, fin);
    if( min == 1 )
        fin->Push(stk2->Pop());
    if( min > 1 )
    {
        while( !stk2->IsEmpty() && min != 0 )
        {
            stk->Push(stk2->Pop());
            min--;
        }
        sort_stack(stk, stk1, stk2, fin);
    }
}


Две проблемы:
1. Зацикливается на повторных элементах... т.е. надо изменить структуру проверки if( max == 1 ), if( min == 1 ), а вот на какую?
2. 31к элемент сортирует за 0.125 секунды
потом время увеличивается по экспоненте...
к 50к элементам приходим за 31.5 секунды, в чем может выражаться эта зависимость?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог