powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тяпничная пирамида
1 сообщений из 126, страница 6 из 6
Тяпничная пирамида
    #39421002
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Затестил сортировку деревом триплетов
Код: plaintext
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.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
// triplet-three

#define TRIPLET_MAX 4096 // Максимальное количество триплетов которые можно использовать

// Интерфейс источника последовательности
class source_t {
	item_t* first = { 0 };		// Первый элемент в последовательности
	bool is_init = { NULL };
public:
	int num = { 0 };

	virtual ~source_t() {}

	void clear() {
		first = NULL;
		is_init = false;
	}

	// Первый элемент в очереди, NULL если пусто
	item_t* front() {
		if (first == NULL && !is_init) {
			is_init = true;
			pop();
		}
		return first;
	}

	// Извлечение следующего элемента
	void pop() {
		first = next();
	}

	// Считывание следующего элемента последовательности, NULL если читать нечего
	virtual item_t* next() {
		assert(false); // должно быть прописано в дочернем классе
		return NULL;
	}
};

// Возрастающая последовательность
class enumerable_t : public source_t {
	item_t* begin = { 0 }; // Первый элемент в последовательности
	item_t* end = { 0 };   // За последним

public:
	// Инициализация
	void init(item_t* begin, item_t* end) {
		assert(begin < end);
		clear();
		this->begin = begin;
		this->end = end;
	}

	// Считывание следующего элемента последовательности, NULL если читать нечего
	item_t* next() override {
		if (begin < end) {
			return begin++; 
		} else {
			return NULL;
		}
	}
};

// Триплет. Слияние двух последовательностей, выдает общую на выходе
class triplet_t : public source_t {
	source_t* src_1 = { 0 };	// Источник 1 вход
	source_t* src_2 = { 0 };	// Источник 2 вход
	source_t* next_pop = { 0 };// Следующий на pop

public:
	// Подключение дочерних источников
	void init(source_t* src1, source_t* src2) {
		src_1 = src1;
		src_2 = src2;
	}

	item_t* next() override {
		// Извлечение следующего
		if (next_pop != NULL) {
			next_pop->pop();
			next_pop = NULL;
		}
		// Выбор следующего
		if (src_2->front() == NULL) {
			next_pop = src_1;
		} else if (src_1->front() == NULL) {
			next_pop = src_2;
		} else if (*src_1->front() < *src_2->front()) {
			next_pop = src_1;
		} else {
			next_pop = src_2;
		}
		return next_pop->front();
	}
};
// Слияние массива src в dest деревом триплетов, возвращает указатель на следующий за последним item_t* triplet_store(source_t** src, size_t src_size, item_t* dest) { assert(src_size != 0); source_t* head; triplet_t trp[TRIPLET_MAX]; if (src_size == 1) { head = src[0]; } else { for (size_t i = 0; i < TRIPLET_MAX; i++) trp[i].num = i + 1000; assert(src_size != 0 || src_size >= TRIPLET_MAX); // Инициализация первых триплетов на src_size входов source_t* alone = NULL; // Не привязанный size_t cnt = 0; for (size_t i = 0; ; i += 2) { if (i == src_size) break; if (i == src_size - 1) { alone = src[i]; break; } trp[cnt].init(src[i], src[i + 1]); cnt++; } // Инициализация остального дерева size_t first = 0, last = cnt; while (last - first > 1) { for (size_t i = first; ; i += 2) { if (i == last) break; if (i == last - 1) { if (alone == NULL) { alone = &trp[i]; } else { trp[cnt].init(&trp[i], alone); cnt++; alone = NULL; } break; } trp[cnt].init(&trp[i], &trp[i + 1]); cnt++; assert(cnt < TRIPLET_MAX); } first = last; last = cnt; } if (alone != NULL) { trp[cnt].init(&trp[first], alone); first = cnt; } head = &trp[first]; } // Сохранение const item_t* i; while (i = head->front()) { *dest = *i; dest++; head->pop(); } return dest; } // Подготовка сортировки. Сортирует a. Возвращает указатель на результат std::vector<item_t>* triplet_three(std::vector<item_t>* a, std::vector<item_t>* b) { enumerable_t enm[TRIPLET_MAX]; source_t* src[TRIPLET_MAX]; size_t repeat = 0; while(repeat != 1) { repeat = 0; item_t* cur = &(*a)[0]; item_t* finish = cur + a->size(); item_t* write = &(*b)[0]; item_t* write_finish = write + b->size(); while(cur < finish) { repeat++; // Поиск последовательностей item_t* first = cur; size_t cnt = 0; while(cnt < TRIPLET_MAX) { item_t* start = cur; item_t* prev = NULL; while(cur < finish && (prev == NULL || !((*cur) < (*prev)))) { prev = cur; cur++; } enm[cnt].init(start, cur); src[cnt] = &enm[cnt]; cnt++; if (cur == finish) { break; } } if (cnt == 1) return a; // Сортировка item_t* write_new = triplet_store(src, cnt, write); write = write_new; } assert(write == write_finish); std::vector<item_t>* t = a; a = b; b = t; } return a; }

[/spoiler]
Алгоритм такой: исходный массив разбивается на последовательности, последовательности даются на вход дереву триплетов.

Код: plaintext
1.
2.
3.
1234
\/\/
 \/
Выход

1234 это источники последовательностей, т.е. 4 упорядоченные последовательности выдающие элементы по возрастанию.

У каждой последовательности есть два метода:
Код: plaintext
1.
2.
3.
4.
5.
// Интерфейс источника последовательности
class source_t {
	virtual const item_t* front() {// Первый элемент в очереди, NULL если пусто
	
	virtual void pop() { // Извлечение следующего элемента


Приемник просто вычитывет инфу пока последовательность не опустеет.

\/ это триплет. На входе две последовательности, на выходе одна. Он проверяет front() входов, и отдает тот что меньше и делает для того входа pop()

Плюс переливание сортированного в другой массив до тех пор пока за 1 перелив не перельется.

Остальные результаты отсюда 20170548

Исходные заполнения
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
#define FILL_ORDERED		2 // Отсортированный
#define FILL_RANDOM		3 // Случайные (диапазон 0...TEST_SIZE*2)
#define FILL_RANDOM_DOUBLES	4 // Случайные с повторами (диапазон 0...100)
#define FILL_STAIRS		5 // Лесенка по 10 (1,2,3,...8,9,1,2,3...)
#define FILL_SINUS		6 // "Синусоида" по 10 (1,2,3,...8,9,8,7,6...)
#define FILL_NEARLY		7 // Почти сортированный (20 значений смещено на 20 позиций)
#define FILL_REVERSE		8 // Обратно сортированный


Время мс
АлгоритмNEARLYORDEREDRANDOMRANDOM_DOUBLESREVERSESINUSSTAIRSinsert_sort()13131311369319128138merge_sort()64363817711164652835836quick_sort()1631621119579176415418std::sort()2712681255344305115127std::stable_sort()4254301238818502601608triplet_tree219829532129169018511540

Копирования и сравнения
Копирования
АлгоритмNEARLYORDEREDRANDOMRANDOM_DOUBLESREVERSESINUSSTAIRSinsert_sort()7900369 072 660102 318 66272 827 95476 243 23879 998 904merge_sort()243 222 784243 222 784243 222 784243 222 784243 222 784243 222 784243 222 784quick_sort()5 807 0165 805 696169 379 23263 116 09720 805 69737 944 05239 390 073std::sort()17 903 42017 902 850363 987 48889 248 99552 799 54856 249 95860 000 051std::stable_sort()209 375 190209 375 000291 879 725291 127 627369 375 000286 375 000280 500 000triplet_tree10 000 000020 000 00020 000 00020 000 00020 000 00020 000 000


Сравнения
АлгоритмNEARLYORDEREDRANDOMRANDOM_DOUBLESREVERSESINUSSTAIRSinsert_sort()10 003 9059 999 999369 299 21096 712 227229 948 65155 283 62962 031 773merge_sort()118 788 350118 788 160220 045 179219 421 541114 434 624210 164 144210 145 472quick_sort()230 640 809230 639 897372 371 596340 441 764235 639 920349 632 120343 247 281std::sort()211 048 809211 048 588373 475 89997 094 945229 825 83855 250 06062 000 101std::stable_sort()116 588 748116 588 568273 242 003272 348 16899 122 124260 926 462261 829 730triplet_tree35 500 2199 999 999238 997 171238 337 713134 434 622249 662 526209 709 873
Так себе по времени, но копирований очень мало: 1-2 переливания всего массива.
...
Рейтинг: 0 / 0
1 сообщений из 126, страница 6 из 6
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тяпничная пирамида
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]