powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Различные структуры данных. Реализация
25 сообщений из 422, страница 14 из 17
Различные структуры данных. Реализация
    #39074544
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЕсли упростить задачу, то у нас есть неупорядоченный массив с уникальными элементами. Для каждого элемента мне нужно определить сколько элементов до него(слева от него) больше него. Асимптотика n^2 и выше меня не устраивает

Это построение индекса. Насколько я себе представляю, в сбалансированном индексе можно легко рассчитать количество элементов на "ветвях" справа и слева. По крайней мере добавляя в индекс последний ключ нужно будет обновить не более log(n) блоков индекса, чтобы скорректировать вес обновленной ветви от листа до корня. И еще два блока, если потребуется балансировка.

Берем очередной элемент, добавляем его в индекс и одновременно суммируем на каждом ярусе дерева, сколько элементов оказалось (меньше/больше). Причем все они находятся до текущего элемента, ведь тех что после в индексе еще нет.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39074550
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Саша давай макет.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39074587
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Структура блока такая:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
struct block {
   string &key;  // Ключ для сравнения
   struct block *gt; // Блок, если искомый ключ больше key. Когда проходим в сторону gt, делаем i_gt++.
   struct block *le; // Блок, если искомый ключ меньше или равен key. Когда проходим в сторону le, делаем sm += i_gt.
   unsigned long i_gt; // Число проходов и добавлений в ветку gt. Балансировка осложняется необходимостью актуализировать i_gt.
   size_t idx; // Индекс элемента в исходном массиве. Заметим, что key == a[idx].key.
 };



// Для затравки добавляем первый ключ.

sm = 0;
struct block *root = { a[0].key, null, bull, 0, 0, 0 };
a[0].i_gt = sm;

ну и т.д.
....
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075008
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabSashaMercuryЕсли упростить задачу, то у нас есть неупорядоченный массив с уникальными элементами. Для каждого элемента мне нужно определить сколько элементов до него(слева от него) больше него. Асимптотика n^2 и выше меня не устраиваетЭто как то уж очень упрощенно и очевидно. Получается нужно один раз пройти список подсчитывая количество просмотренных элементов и каждому элементу списка присвоить текущее значение счетчика.

Но каждое удаление элемента приведет к сдвигу хвоста списка. В массиве, это сдвиг элементов, в односвязном списке это перенумерация элементов. Думаю, в этом смысле альтернатив нет.

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

Или перед удалением пробегать всю голову, но сравнивая ключ.

Трудно сказать что быстрее. От данных зависит.

Асимптотика должна быть одинаковой, так что ничего не быстрее
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075011
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Асимптотика добавления в дерево зависит от его высоты, а высота его зависит от того в каком порядке в него попадают данные, и может варьироваться от до . Нельзя гарантировать что порядок данных будет хорошим
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075013
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryАсимптотика добавления в дерево зависит от его высоты, а высота его зависит от того в каком порядке в него попадают данные, и может варьироваться от до . Нельзя гарантировать что порядок данных будет хорошим
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075033
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury,

эх, вот придумал бы ты балансировку для 2-D дерева за log(n), сразу стал бы знаменитым
позвали бы тебя для баз всяких алгоритмы придумывать
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075077
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercurySashaMercuryАсимптотика добавления в дерево зависит от его высоты, а высота его зависит от того в каком порядке в него попадают данные, и может варьироваться от до . Нельзя гарантировать что порядок данных будет хорошим



Высота сбалансированного дерева (АВЛ-дерево) равна log(n) для любых исходных данных. От распределения данных зависит только число вращений вершин во время добавления или удаления.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075088
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabSashaMercuryпропущено...




Высота сбалансированного дерева (АВЛ-дерево) равна log(n) для любых исходных данных. От распределения данных зависит только число вращений вершин во время добавления или удаления.

Это близко, но на самом деле не так.

Если использовать сбалансированные деревья (AVL или RB), то задачу пожалуй можно решить. Я ещё думаю, стоит ли оно того, может быть есть другие способы её решения
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075173
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercurymcureenabпропущено...


Высота сбалансированного дерева (АВЛ-дерево) равна log(n) для любых исходных данных. От распределения данных зависит только число вращений вершин во время добавления или удаления.

Это близко, но на самом деле не так.

Разница длинны двух любых маршрутов от корня к листьям в АВЛ дереве 0 или 1. Это существенно только для совсем маленького объема данных, когда в дереве мало ярусов. Но наверное никакая структура или алгоритм не даст в общем случае все маршруты равной длинны. Форма дерева в общем случае будет зависеть от порядка исходных данных, но когда ярусов много, это несущественно.

У тебя еще какие то соображения есть?
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075429
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabSashaMercuryпропущено...


Это близко, но на самом деле не так.

Разница длинны двух любых маршрутов от корня к листьям в АВЛ дереве 0 или 1. Это существенно только для совсем маленького объема данных, когда в дереве мало ярусов. Но наверное никакая структура или алгоритм не даст в общем случае все маршруты равной длинны. Форма дерева в общем случае будет зависеть от порядка исходных данных, но когда ярусов много, это несущественно.

У тебя еще какие то соображения есть?

Ваше первое утверждение не совсем верно, вот и всё. Одно дело если вы используете O нотацию и говорите об оценках, но если вы говорите конкретные функции, то вы ошибаетесь. Используя O-нотацию мы имеем
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39075862
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.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Замер времени
class timer {
	clock_t start;
	char buf[20];
public:
	timer();
	void init(); // начало замера
	const char* value(); // текущее значение
};

timer::timer()
{
	init();
}

void timer::init()
{
	start = clock();
}

// Вывод времени
const char* timer::value()
{
	clock_t t = clock() - start;
	int sec = t / CLOCKS_PER_SEC;
	if(sec > 1000) {
		sprintf(buf, "%.0f sec", (double)t / CLOCKS_PER_SEC);
	} else if(sec > 100) {
		sprintf(buf, "%.1f sec", (double)t / CLOCKS_PER_SEC);
	} else if(sec > 10) {
		sprintf(buf, "%.2f sec", (double)t / CLOCKS_PER_SEC);
	} else {
		sprintf(buf, "%.3f sec", (double)t / CLOCKS_PER_SEC);
	}
	return buf;
}

//******************************************************
// Размер тестового массива
#define TEST_SIZE 50000
//******************************************************

// Заполнение исходных данных
void init(int* arr)
{
	timer t;
	// Заполняем уникальными значениями
	for(int i = 0; i != TEST_SIZE; i++) arr[i] = i;
	// Перемешиваем
	int r = 54323; // ГСЧ с постоянной последовательстью
	for(int i = 0; i != TEST_SIZE; i++) {
		do {
			r = (r * 12347 + 1) % TEST_SIZE;
		} while(r < 0);
		
		int j = arr[i];
		arr[i] = arr[r];
		arr[r] = j;
	}
	printf("Init %u elements. %s\n", TEST_SIZE, t.value());
}

// Вывод содержимого массива
void print(const char* text, int* arr)
{
	printf(text);
	unsigned int check = 0;
	for(int i = 0; i < TEST_SIZE; i++) {
		if(i < 10) printf("%d ", arr[i]);
		check += i * arr[i];
	}
	printf(" sum %X\n", check);
}

// Решение перебором
void perebor(int* data, int* res)
{
	timer t;
	for(int i = 0; i < TEST_SIZE; i++) {
		for(int j = 0; j < i; j++) {
			if(data[j] > data[i]) res[i]++;
		}
	}
	printf("Perebor %s\n", t.value());
}

int main(int argc, char* argv[])
{

	int* data = (int*)calloc(TEST_SIZE, sizeof(int)); // массив исходных данных
	int* res = (int*)calloc(TEST_SIZE, sizeof(int)); // массив для результата
	if(!data || !res) {
		printf("No memory\n");
	} else {
		// Заполнение исходных данных
		init(data); 
		print("Data   ", data);
		// Расчет
		perebor(data, res); // менять на свое
		// Вывод результата
		print("Result ", res);
	}

	if(data) free(data);
	if(res) free(res);

	system("pause");
	return 0;
}


Там решение только перебором. Но есть генератор исходных данных, замер времени, вывод данных и результата с контрольной суммой.

Кому интересно: писать свою функцию вместо perebor(). Перебор не быстро работает. 1,5 сек для массива в 50 тыс. элементов. 6 сек для 100 тыс. Чистый N^2

Попробую свою идею 18266267 затестить на скорость. Надо только определиться можно исходные данные портить или нет. Предлагаю портить, т.к. несложно биткарту добавить для пометок, сложность от этого не изменится, но лишний код добавится.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39076116
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почему используется именно 12347?
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39076128
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПочему используется именно 12347?
12345 как-то не очень перемешивало, взял ближайшее простое.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39097902
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.
Известно что некоторые структуры данных можно реализовать разными способами. Например, очередь можно реализовать с использованием двусвязного списка, либо с использованием непрерывной области памяти, и др. Но как нам известно у любой очереди существуют интерфейсы(если это слово корректно употребить в данном случае) dequeue и enqueue. Правильно ли я понимаю, что для того чтобы реализовать различный вариации определения очередей(здесь слово 'определение' понимается в контексте class definition) грамотным будет первым делом создать некий базовый тип(класс), и наследовать вариации различных определений от него ? Но тогда возникает такой вопрос, данный класс должен быть абстрактным классов, либо достаточно определить все методы этого класса с меткой protecded ? Подскажите пожалуйста
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39097908
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЗдравствуйте.
Известно что некоторые структуры данных можно реализовать разными способами. Например, очередь можно реализовать с использованием двусвязного списка, либо с использованием непрерывной области памяти, и др. Но как нам известно у любой очереди существуют интерфейсы(если это слово корректно употребить в данном случае) dequeue и enqueue. Правильно ли я понимаю, что для того чтобы реализовать различный вариации определения очередей(здесь слово 'определение' понимается в контексте class definition) грамотным будет первым делом создать некий базовый тип(класс), и наследовать вариации различных определений от него ? Но тогда возникает такой вопрос, данный класс должен быть абстрактным классов, либо достаточно определить все методы этого класса с меткой protecded ? Подскажите пожалуйста
если в плане ООП, то да, наследование от базового класса
но в плане эффективности это не гуд, поэтому и используют шаблоны\макросы где все вызовы в итоге можно сделать статическими и компилятор может агрессивно задействовать оптимизацию
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39097925
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)SashaMercuryЗдравствуйте.
Известно что некоторые структуры данных можно реализовать разными способами. Например, очередь можно реализовать с использованием двусвязного списка, либо с использованием непрерывной области памяти, и др. Но как нам известно у любой очереди существуют интерфейсы(если это слово корректно употребить в данном случае) dequeue и enqueue. Правильно ли я понимаю, что для того чтобы реализовать различный вариации определения очередей(здесь слово 'определение' понимается в контексте class definition) грамотным будет первым делом создать некий базовый тип(класс), и наследовать вариации различных определений от него ? Но тогда возникает такой вопрос, данный класс должен быть абстрактным классов, либо достаточно определить все методы этого класса с меткой protecded ? Подскажите пожалуйста
если в плане ООП, то да, наследование от базового класса
но в плане эффективности это не гуд, поэтому и используют шаблоны\макросы где все вызовы в итоге можно сделать статическими и компилятор может агрессивно задействовать оптимизацию

Что такое ООП мы все понимаем по разному. Мне нужно чтобы это было грамотно и правильно. Использование типов должно быть. Но правильное проектирование типов(классов) вопрос сложный. Мне не очень понятно почему при таком проектировании, должны возникнуть проблемы на которые вы указали, поясните пожалуйста
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39097953
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот только получается что абстрактный класс о котором я говорил выше должен быть оформлен в виде шаблона класса
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39097968
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЧто такое ООП мы все понимаем по разному. Мне нужно чтобы это было грамотно и правильно. Использование типов должно быть. Но правильное проектирование типов(классов) вопрос сложный. Мне не очень понятно почему при таком проектировании, должны возникнуть проблемы на которые вы указали, поясните пожалуйста
В ООП как и в других ученьях есть различные философии и практики.
Если следовать SOLID то я бы акцентировал внимание на 4-й принцип (буква I)
рекомендует Interface segregation principle (Много специализированных интерфейсов лучше, чем один универсальный.) .
Если в queue на базе памяти и двузсвязного списка можно выделить два и более
интерфейса - то я бы это сделал.

Не знаю про какую такую эффективность толкует Руслан - но скорее всего речь
идёт об оптимизации вирутального вызова. Если говорить о макросах - то это не
есть ООП. Это нечто более примитивное и механическое. В С++ шаблоны+макросы
возведены в особый ранг технических приёмов которые и делают С++ быстрым.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39098040
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryВот только получается что абстрактный класс о котором я говорил выше должен быть оформлен в виде шаблона класса
ну вот видишь, смысл тогда от всей этой дребедени с наследованием, полиморфизмом, сделал шаблон и не паришься
названия одинаковые методам дай да и всё, хочешь массив, используй шаблон с массивом, хочешь классическую - тоже проблем нет
всё у тебя разложится в конкретный код, нужный тебе именно для этого типа и с нужным тебе алгоритмом и структурой хранения

в STL работает, ёжики колются, но .. - эффективнее по использованию и скорости придумать малореально
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39099062
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)SashaMercuryВот только получается что абстрактный класс о котором я говорил выше должен быть оформлен в виде шаблона класса
ну вот видишь, смысл тогда от всей этой дребедени с наследованием, полиморфизмом, сделал шаблон и не паришься
названия одинаковые методам дай да и всё, хочешь массив, используй шаблон с массивом, хочешь классическую - тоже проблем нет
всё у тебя разложится в конкретный код, нужный тебе именно для этого типа и с нужным тебе алгоритмом и структурой хранения

в STL работает, ёжики колются, но .. - эффективнее по использованию и скорости придумать малореально

Шаблоны будут для нескольких реализаций независимо от того будет ли абстрактный класс или нет.
В любом случае спасибо всем, решил отказаться от этой идеи в силу того что не так глубоко изучил абстрактные классы, и советов выше.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39099108
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только вот что странно, раньше, когда у меня был просто класс, и было три файла:
q.h, q.cpp, и в main.cpp я подключал q.h программа собиралась корректно. Теперь я сделал класс шаблонным, определение методов в q.cpp выглядит следующим образом

Код: plaintext
1.
2.
3.
4.
5.
template <typename T>
queue1<T>::queue1()
{
	//smth 
}



происходит ошибка при сборке. Становятся невидимыми определения этих методов(из q.cpp). Это связано с тем что класс стал шаблонным, и собирать его нужно иначе ?
PS когда подключаю в main q.cpp всё ок, но мне это не нравится.
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39099116
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryТолько вот что странно, раньше, когда у меня был просто класс, и было три файла:
q.h, q.cpp, и в main.cpp я подключал q.h программа собиралась корректно. Теперь я сделал класс шаблонным, определение методов в q.cpp выглядит следующим образом

Код: plaintext
1.
2.
3.
4.
5.
template <typename T>
queue1<T>::queue1()
{
	//smth 
}



происходит ошибка при сборке. Становятся невидимыми определения этих методов(из q.cpp). Это связано с тем что класс стал шаблонным, и собирать его нужно иначе ?
PS когда подключаю в main q.cpp всё ок, но мне это не нравится.


весь код шаблоный должен быть в заголовке .
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39099120
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почему так ?
...
Рейтинг: 0 / 0
Различные структуры данных. Реализация
    #39099234
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПочему так ?компилятор должен ведь знать, чего именно ему генерить, не?
...
Рейтинг: 0 / 0
25 сообщений из 422, страница 14 из 17
Форумы / C++ [игнор отключен] [закрыт для гостей] / Различные структуры данных. Реализация
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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