27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
1

Каковы варианты сортировки связного списка

05.09.2014, 00:45. Показов 5314. Ответов 23
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Дорого времени суток.
Есть двусвязный список хранящий допустим int, какие есть варианты по его сортировки?
Например:
1. Считать все данные со списка в массив, отсортировать массив (можно через указатели), удаляем старый список и записываем новый (сортировать напрямую почему то не вышло((( );
2. При добавлении данных в список, вставлять > data > ;

Подскажите свои/правильный вариант...
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.09.2014, 00:45
Ответы с готовыми решениями:

Не срабатывает функция сортировки связного списка
Добрый день! Не срабатывает функция сортировки связного списка. Как студент, буду благодарен за...

Создание двойного связного списка целых чисел, вводимых с клавиатуры; печать списка
Люди помогите, нужно сдать последнюю Лабу. Задача: Написать программу которая создает двойной...

Напишите процедуру сортировки линейного связного списка методом простого выбора с изменением указателей
Вот программа создающая линейный связный список. Type Ukazatel = ^S; S = Record Data : string;...

Каковы варианты решения?)
на сайте есть на одном сайте есть: edit1 edit2 button вот надо два эдита заполнить сбазы и...

23
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
05.09.2014, 00:51 2
Цитата Сообщение от andreyananas Посмотреть сообщение
какие есть варианты по его сортировки
Пузырьковая сортировка может подойти, так как в ней нужен только указатель на текущий и следующий элемент и она не нуждается в индексировании в данном случае.
0
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
05.09.2014, 00:57  [ТС] 3
Цитата Сообщение от Dani Посмотреть сообщение
Пузырьковая сортировка может подойти, так как в ней нужен только указатель на текущий и следующий элемент и она не нуждается в индексировании в данном случае.
что то не догоняю, можно пример набросать?
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
05.09.2014, 01:04 4
Обычная сортировка пузырьком:
C++
1
2
3
4
for(int i=0; i<n-1; ++i)
 for(int j=0; j<n-i-1; ++j)
  if(a[j] > a[j+1])
   swap(a[j], a[j+1]);
Как можно заметить, здесь на каждой итерации цикла нужны лишь 2 указателя (элемента): a[j] и a[j+1] (следующий за a[j]).
Списки не поддерживают быструю операцию индексирования. Ее можно реализовать так, но ее сложность будет O(N), где N - количество элементов в списке:
C++
1
2
3
T* find;
for(int i=0; i<x; ++i) //ищем x-тый элемент
 find = find->next; //переходим к след. элементу
Если использовать сортировку пузырьком для списков, то операции индексирования не понадобится, так как можно сделать так:
C++
1
2
3
4
5
6
7
8
9
10
List a, b;
 
for(int i=0; i<n-1; ++i)
 {
  a = l.begin; //начало списка
  b = a;
  b = b.next;
  for(int j=0; j<n-i-1; ++j, a= a.next, b = b.next)
   if(a.value > b.value)
    swap(a.value, b.value);
0
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
05.09.2014, 10:48  [ТС] 5
Цитата Сообщение от Dani Посмотреть сообщение
Если использовать сортировку пузырьком для списков, то операции индексирования не понадобится, так как можно сделать так:

C++
1
2
3
4
5
6
7
8
9
10
List a, b;
for(int i=0; i<n-1; ++i)
{
 a = l.begin; //начало списка
 b = a;
 b = b.next;
for(int j=0; j<n-i-1; ++j, a= a.next, b = b.next)
if(a.value > b.value)
 swap(a.value, b.value);
}
Либо я что то не понимаю, либо тут мы "двигаем" данные. Если это так, разве это приемлемо?

Добавлено через 9 часов 32 минуты
тема все еще актуальна...
0
20 / 20 / 3
Регистрация: 25.05.2011
Сообщений: 62
05.09.2014, 11:24 6
Если честно, я вообще не понял, при чем тут индексация и приведенный код. Возможно человек просто не все вставил из буфера обмена.
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
05.09.2014, 19:30 7
Цитата Сообщение от grindaah Посмотреть сообщение
индексация и приведенный код
Например, быстрая сортировка со сложностью O(n*log(n)) для списка не подойдет, так как ее реализация нуждается в индексировании. У сортировки пузырьком этой проблемы нет.
1
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
06.09.2014, 10:00  [ТС] 8
апппп
все еще актуальный вопрос....
Цитата Сообщение от andreyananas Посмотреть сообщение
Есть двусвязный список хранящий допустим int, какие есть варианты по его сортировки?
Например:
1. Считать все данные со списка в массив, отсортировать массив (можно через указатели), удаляем старый список и записываем новый (сортировать напрямую почему то не вышло((( );
2. При добавлении данных в список, вставлять > data > ;
Подскажите свои/правильный вариант...
0
2662 / 2237 / 240
Регистрация: 03.07.2012
Сообщений: 8,138
Записей в блоге: 1
06.09.2014, 10:10 9
Если это не учебная задача, а практическая, то используй контейнер list из STL.
0
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
06.09.2014, 10:11  [ТС] 10
Цитата Сообщение от zer0mail Посмотреть сообщение
Если это не учебная задача, а практическая, то используй контейнер list из STL.
это задача цель которой... понять)
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
06.09.2014, 10:16 11
Цитата Сообщение от Dani Посмотреть сообщение
Как можно заметить, здесь на каждой итерации цикла нужны лишь 2 указателя (элемента): a[j] и a[j+1] (следующий за a[j]).
Точнее даже не так. Нужны a+j и a+j+1. a - это не только массив, но и указатель на начало этого массива.
0
2662 / 2237 / 240
Регистрация: 03.07.2012
Сообщений: 8,138
Записей в блоге: 1
06.09.2014, 10:27 12
Тогда надо понять, что именно хочется понять Если как манипулировать указателями, то выгрузка-сортировка-загрузка не помогут. И т.д.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
06.09.2014, 10:30 13
Берём
C++
1
2
3
4
5
6
7
8
9
10
11
12
for (i=0; i<n-1; ++i)
{
 for (j=i+1; j<n; ++j)
 {
  if (a[i]>a[j])
  {
   t=a[i];
   a[i]=a[j];
   a[j]=t;
  }
 }
}
Строки 7-9 - это обмен местами a[i] и a[j]. a[i] - это на самом деле *(a+i), a[j] - это *(a+j). Переписываем на адресную арифметику, объявив i и j, как указатели на элемент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
for (i=a; i<a+n-2; ++i)
{
 for (j=i+1; j<a+n-1; ++j)
 {
  if (*i>*j)
  {
   t=*i;
   *i=*j;
   *j=t;
  }
 }
}
. Остаётся учесть реализацию контейнера:
C++
1
2
3
4
5
6
7
8
9
10
11
12
for (i=list; i->next!=NULL; i=i->next)
{
 for (j=i->next; j!=NULL; j=j->next)
 {
  if (i->Data>j->Data)
  {
   t=i->Data;
   i->Data=j->Data;
   j->Data=t;
  }
 }
}
.
1
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
06.09.2014, 10:34  [ТС] 14
Цитата Сообщение от zer0mail Посмотреть сообщение
Тогда надо понять, что именно хочется понять Если как манипулировать указателями, то выгрузка-сортировка-загрузка не помогут. И т.д.
хм... понять, каким способом лучше сортировать двусвязный список.
0
2662 / 2237 / 240
Регистрация: 03.07.2012
Сообщений: 8,138
Записей в блоге: 1
06.09.2014, 10:55 15
Вообще-то списки часто используются для хранения структур и сортировку приходится делать по полю списка. В этом случае перестановка значений одного поля не подойдет, надо перебрасывать указатели. Для изучения работы с указателями это годится, а для решения реальных задач сортировки лучше использовать STL, например. Там и скорость написания (когда ее освоишь) и скорость работы и универсальность.
Я даже думаю, что если программист может освоить STL, он должен ее освоить А если не может, то ему лучше изучать другой язык, не C++
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
06.09.2014, 11:31 16
Можно аналогично перемещать все поля. Кроме того, структура может валять в ->Data.

Добавлено через 30 минут
Но если охота съэкономить операции, то:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for (p=&list, i=list; i->next!=NULL; p=&i->Next, i=i->next)
{
 for (j=i->next; j!=NULL; j=j->next)
 {
  if (i->Key>j->Key)
  {
   *p=j;
   tp=i->previus;
   tn=i->next;
   ti=i;
   j->previus->next=i;
   i->previus=j->previus;
   i->next=j->next;
   j->previus=tp;
   j->next=tn;
   i=j;
   j=ti;
  }
 }
}
. Можно аналогично переделать и другие алгоритмы.
0
Заблокирован
Автор FAQ
06.09.2014, 11:37 17
Лучший ответ Сообщение было отмечено andreyananas как решение

Решение

andreyananas, лови
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <iostream>
using namespace std;
 
template<class T>
struct ListItem
{
    T data;
    ListItem<T> * prev;
    ListItem<T> * next;
    ListItem<T>(){
        data = 0;
        prev = 0;
        next = 0;
    }
    void Swap(ListItem<T> * elem = 0){
        T buf = data;
        if( elem )
        {
            data = elem->data;
            elem->data = buf;
        }
    }
};
 
template<class T>
class CList{
    protected:
    ListItem<T> * beg;
    ListItem<T> * end;
    public:
    CList();
    void Add (T value);
    void Init(T * arr, int size);
    void Show();
    void Sort(bool bascent = true);
    int size();
    ListItem<T> * at(int elem);
};
template<class T>
CList<T>::CList(){
    beg = 0;
    end = 0;
}
template<class T>
void CList<T>::Add (T value){
    if( beg )
    {
        end->next = new ListItem<T>();
        end->next->prev = end;
        end = end->next;
    }
    else
    {
        beg = new ListItem<T>();
        end = beg;
    }
    if( end )
        end->data = value;
}
template<class T>
void CList<T>::Init(T * arr, int size){
    for( int i = 0; i < size; i++ )
        Add (arr[i]);
}
template<class T>
void CList<T>::Show(){
    ListItem<T> * elem = 0;
    for( elem = beg; elem; elem = elem->next)
        cout<<elem->data<<" ";
}
template<class T>
int CList<T>::size(){
    int size = 0;
    ListItem<T> * elem = 0;
    for( elem = beg; elem; elem = elem->next)
        size++;
    return size;
}
template<class T>
ListItem<T> * CList<T>::at(int index){
    ListItem<T> * elem = 0;
    for( elem = beg; elem && index; elem = elem->next)
        index--;
    return elem;  
}
template<class T>
void CList<T>::Sort(bool bascent){
     ListItem<T> * elem = 0;
     ListItem<T> * item = 0;
     int i, j;
     int size = this->size();
     for( i = 0; i < size; i++ )
     for( j = 0; j < size; j++ )
     {
        elem = at(i);
        item = at(j);
        if( elem && item )
        {
            if( bascent ? (elem->data > item->data) : (elem->data < item->data) )
                elem->Swap(item);
        }
     }
}
 
int main(){
    CList<int> list;
    int arr[] = {5, -3, 14, 44, -2, 11, 1, 3, 5, 17, 46};
    int size  = sizeof(arr) / sizeof(arr[0]);
    list.Init(arr, size);
    cout<<"\n\tINIT : "<<endl;
    list.Show();
    list.Sort();
    cout<<"\n\tSORT : "<<endl;
    list.Show();
    return 0;
}
http://codepad.org/Oz9oXKP8
INIT :
5 -3 14 44 -2 11 1 3 5 17 46
SORT :
46 44 17 14 11 5 5 3 1 -2 -3

Не по теме:

ЗЫ Такие задания без реализации списка в заголовке темы никто не любит, т.к минимум нужно писать свою реализацию списка. Учти это на будующее когда будешь просить помогать с подобными задачами.

Миниатюры
Каковы варианты сортировки связного списка  
2
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
06.09.2014, 12:08 18
Цитата Сообщение от Dani Посмотреть сообщение
Например, быстрая сортировка со сложностью O(n*log(n)) для списка не подойдет, так как ее реализация нуждается в индексировании.
Какая жестокая ошибка... Быстрая сортировка (разумеется, без индексирования) как раз отлично подходит для списков. Что может быть проще, чем сделать из одного списка два, а потом срастить их обратно?
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
06.09.2014, 16:58 19
Цитата Сообщение от Nick Alte Посмотреть сообщение
Что может быть проще, чем сделать из одного списка два, а потом срастить их обратно?
Выбор опорного элемента. Как его выбрать быстро в списке? Брать первый или последний элемент ухудшит ассимптотику. Решается набором костылей, например, поддерживать доп. массив значений и в каждом элементе списка хранить позицию, на которой он находится в этом массиве.
С этим дополнительным массивом выходит, тоже самое, что и сортировка массива.

Добавлено через 9 минут
Хм. Если выбирать рандомный элемент и проходить к нему по списку, то кол-во операций увеличивается в 1,5 раза. Некритично, признаю свою ошибку
Кстати, тут и склеивание списков не понадобится.
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
06.09.2014, 19:06 20
А если попробовать брать среднее арифметическое двух первых элементов, может получиться даже ещё лучше.
0
06.09.2014, 19:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.09.2014, 19:06
Помогаю со студенческими работами здесь

Каковы варианты создания строки навигации по дереву (как, например, в Windows - строка пути)
Тук тук :) Сразу см скрин. Вот в винде есть в экплорере строка навигации по папкам. Хочу сделать...

Сортировка связного списка
Помогите написать сортировку связного списка по мере добавления в него элементов

Реализация связного списка
надо решить задачу: Сведения о владельце автомобиля: фамилия, марка автомобиля (строки), номер...

Сортировка связного списка
Проставить сложность для алгоритмов сортировки связного списка и дать ответ на два вопроса:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru