powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Мера неупорядоченности линейного массива и некоторые вопросы
53 сообщений из 53, показаны все 3 страниц
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076248
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.
Раздел "Различные структуры данных. Реализация" предназначен скорее для теоретических вопросов в контексте С++. Потому я решил не продолжать в нём дискуссию по данному конкретному вопросу. Спасибо Дмитрию и другим кто высказал своё мнение ранее.

Постановка задачи 1.

Для любого линейного непрерывного индексного массива T a[], размером n введём норму/меру неупорядоченности/measure по следующему правилу
, где . Необходимо разработать алгоритм с асимптотической сложностью.
Приведу пример: Пусть A задано следующим множеством чисел А = { 17, 5, 18, 1, 3, 4, 7, 11, 85, 8, 9 }. Тогда его мера равна:
.

Постановка задачи 2.
Пусть в постановке 1 исходный индексный массив содержит в себе только уникальные элементы.


Мне, вообще говоря, интересна 2 постановка. Ниже представлено решение асимптотика которого представима в виде суперлинейной функции. Попозже попробую решить используя сбалансированные деревья, и сравню со своим первым решением и с вариантом Дмитрия(n^2) на конкретных данных. Данный вариант работает правильно(судя по моим проверкам), но на мой взгляд реализован(с точки зрения проектирования и реализации типов данных) не очень хорошо(скорее всего плохо).

Код: 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>

struct node
{
	int value;//key
	int counter;//number of elements in the tree over then current at time of adding
	int counter_r;//number of elements right subtree
	node *left, *right;
	void print();
};

void node::print()
{
	printf("%i %i %i   \n", value, counter_r, counter);
}

class tree
{
	node* root;
	int measure;
	void insert(node*& n, int v, int c);
	void print(node* n);
	void measure_calculate(node* n);
public:
	tree();
	tree(int* a, size_t n);
	void print();
	void measure_calculate();
	int measure_get();
};

tree::tree()
{
	root = NULL;
	measure = 0;
}

tree::tree(int* a, size_t n)
{
	root = NULL;
	measure = 0;
	for (int i = 0; i < n; ++i){
		this->insert(root, a[i], 0);
	}
}

void tree::insert(node*& n, int v, int c)
{
	node* cur;
	if (n == NULL){
		cur = (node*)malloc(sizeof(node)* 1);
		cur->value = v;
		cur->left = NULL;
		cur->right = NULL;
		cur->counter_r = 0;
		cur->counter = c;
		n = cur;
	}
	else{
		if (n->value > v){
			this->insert(n->left, v, c + n->counter_r + 1);
		}
		else{
			n->counter_r += 1;
			this->insert(n->right, v, c);
		}
	}
}

void tree::print()
{
	print(root);
}

void tree::print(node* n)
{
	if (n){
		print(n->left);
		n->print();
		print(n->right);
	}
}


void tree::measure_calculate()
{
	measure_calculate(root);
}

void tree::measure_calculate(node* n)
{
	if (n){
		measure_calculate(n->left);
		measure += n->counter;
		measure_calculate(n->right);
	}
}

int tree::measure_get()
{
	return measure;
}


int main()
{
	int b[11] = { 17, 5, 18, 1, 3, 4, 7, 11, 85, 8, 9 };
	tree t(b, 11);
	t.measure_calculate();
	printf("%i\n", t.measure_get());
	return 0;
}



1. measure лучше выделить в отдельный класс
2. Перегруженный деструктор(если можно так сказать) почему-то не работает так как должен работать. Потому я его убрал пока
3. и др

Подскажите пожалуйста в чём главные ошибки по реализации программы в оос. И может быть у кого-то есть ещё соображения по реализации алгоритма (с линейной скоростью или с лучшей организацией дерева за исключением вопросов балансировки(на данный момент))

PS
Я ещё не прочитал статью о различиях между malloc и new потому пока использую malloc, вы в своих программах на С++ используете только new ?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076254
RWolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЯ ещё не прочитал статью о различиях между malloc и new потому пока использую malloc, вы в своих программах на С++ используете только new ?
malloc выделяет неинициализированный кусок памяти, new создаёт объект.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076285
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RWolfSashaMercuryЯ ещё не прочитал статью о различиях между malloc и new потому пока использую malloc, вы в своих программах на С++ используете только new ?
malloc выделяет неинициализированный кусок памяти, new создаёт объект.

Дефолтный new это вызов p = malloc... и вызов конструктора для p == this. В случае new [N], выделяется память под N объектов и для каждого вызывается конструктор.
Дефолтный delete, вызывает деструктор, потом free. В случае delete [], вызывается деструктор для каждого элемента массива, потом free для всего массива.

Нужно заметить, что в процессе конструирования и разрушения объекта происходит инициализация не только атрибутов, но и таблицы виртуальных методов (если они применяются). Прямого доступа к таблицам виртуальных методов у программиста нет.

Можно создать собственные new и delete и использовать в них иной менеджер памяти, отличный от стандартной кучи.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076333
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЯ ещё не прочитал статью о различиях между malloc и new потому пока использую malloc, вы в своих программах на С++ используете только new ?

Для создания объектов динамически -- new.
Для выделения просто памяти -- можно и malloc.

new в С++ выделяет память и инициализирует в этой памяти объект с помощью конструктора.
malloc про объекты вообще ничего не знает.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076403
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eсть еще вариант обойтись и без new и без malloc в своем коде, на стандартных контейнерах, make_unique и make_shared.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076527
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Саша. Что такое СУПЕР ЛИНЕЙНАЯ функция?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39076730
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал по этому алгоритму 18266267
Работает побыстрее перебора. На 100 тыс. элементов перебор 6.2 сек. этот 0.04 сек
Вот замеры
ЭлементовВремя1 млн.0.52 сек.2 млн.1.4 сек.3 млн.2.5 сек.4 млн.3.78 сек.8 млн.10.4 сек.
Попробовал сложность оценить, если сравнить с O(n * log2(n)) то вроде как даже чуть быстрее.
Например 8*log(8) = 24, у меня 10.4 / 0.52 = 20.

Исходник
Код: 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.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.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 10000
//******************************************************

// Заполнение исходных данных
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 compare_int(const void* a, const void* b)
{
  return ( **(int**)a - **(int**)b );
}

// С сортировкой и массивом счетчиков
void with_counter(int* data, int* res)
{
	timer t;
	int** idx = (int**)malloc(TEST_SIZE * sizeof(int*)); // индексы сортировки
	if(!idx) {
		printf("No memory\n");
		return;
	}
	// Заполнение индексов и сортировка
	for(int i = 0; i < TEST_SIZE; i++) idx[i] = &data[i];
	qsort(idx, TEST_SIZE, sizeof(int*), compare_int);

	// Выбор шага счетчика
	int step = 2; 
	int step_bit = 1; 
	int y = TEST_SIZE;
	while(true) {
		int x = step / 2 + TEST_SIZE / (step * 2);
		if(x > y || step >= TEST_SIZE) {
			step >>= 1;
			step_bit--;
			break;
		}
		y = x;
		step <<= 1;
		step_bit++;
	}
	// Массив счетчиков
	int cnt_size = TEST_SIZE / step + 1;
	int* cnt = (int*) malloc(cnt_size * sizeof(int)); // счетчики
	if(!cnt) {
		printf("No memory\n");
		free(idx);
		return;
	}
	for(int i = 0; i < cnt_size; i++) cnt[i] = step;
	// Расчет
	int min = *idx[0];
	int mask = 0x7FFFFFFF ^ (step - 1); // маска для поиска первого элемента группы
	for(int i = 0; i < TEST_SIZE; i++) {
		int pos = idx[i] - data; // индекс минимального элемента в data
		 // обнуление посчитанного
		data[pos] = min;
		int cnt_pos = pos >> step_bit; // индекс счетчика
		cnt[cnt_pos]--;
		// Подсчет от начала группы
		for(int j = pos & mask; j < pos; j++) {
			if(data[j] > data[pos]) res[pos]++;
		}
		// Добавление полных групп
		for(int j = 0; j < cnt_pos; j++) {
			res[pos] += cnt[j];
		}
	}
	free(cnt);
	free(idx);
	printf("Counters %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);
		memset(res, 0, sizeof(int)*TEST_SIZE);

		// Расчет c сортировкой и групповыми счетчиками
		with_counter(data, res);
		// Вывод результата
		print("Result ", res);
	}

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

	system("pause");
	return 0;
}

...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077070
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может быть я не так перевожу, но в англоязычной литературе встречается термин superlinear function. Скорость роста данной функции выше чем у линейной функции, например, асимптотика quick sort принадлежит классу superlinear function, и составляет . Так и тут
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077081
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, мне кажется он работает. Почему вывод времени реализован так как он реализован ?
Можно ли упростить реализацию with_counter() не меняя алгоритм ?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077090
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПочему вывод времени реализован так как он реализован ?
Что конкретно интересует?
Максимально упростил использование. Для замера достаточно создать объект, а в конце получить его состояние.
SashaMercuryМожно ли упростить реализацию with_counter() не меняя алгоритм ?
Думаю что нет. Разве что в начале подбор шага переделать на формулу. Там идет поиск минимума step / 2 + TEST_SIZE / (step * 2)
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077091
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделать вывод временив одном формате независимо от того какое у нас время(1 секунда или 10)
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077092
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просто не понял почему вывод времени сделан именно так. Можно было вывести в одном формате
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077100
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПросто не понял почему вывод времени сделан именно так. Можно было вывести в одном формате
Для читабельности. Чтобы лишнего не было. Время надо для сравнительной оценки. Точности в 0,1% вполне достаточно, т.е. надо 3 первых десятичных знака. Поэтому зачем писать лишнее если можно не писать.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077106
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДмитрийДумаю что нет. Разве что в начале подбор шага переделать на формулу. Там идет поиск минимума step / 2 + TEST_SIZE / (step * 2)

Этим минимумом будут либо значения на границах, либо в точке. Если я правильно понял. Разве не так ?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077115
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде так, только надо еще округлить до ближайшей степени двойки. Я специально так сделал, чтобы исключить деление и остатки от деления.
т.е. для 1 млн должно получиться 1024, для 100 млн. - 8192.

Можно попробовать точное значение брать, делений не так уж и много будет. Поправлю попозже.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077164
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.
// С сортировкой и массивом счетчиков
void with_counter(int* data, int* res)
{
	timer t;
	int** idx = (int**)malloc(TEST_SIZE * sizeof(int*)); // индексы сортировки
	if(!idx) {
		printf("No memory\n");
		return;
	}
	// Заполнение индексов и сортировка
	for(int i = 0; i < TEST_SIZE; i++) idx[i] = &data[i];
	qsort(idx, TEST_SIZE, sizeof(int*), compare_int);

	// Выбор шага счетчика
	int step = (int)sqrt((double)TEST_SIZE);
	// Массив счетчиков
	int cnt_size = TEST_SIZE / step + 1;
	int* cnt = (int*) malloc(cnt_size * sizeof(int)); // счетчики
	if(!cnt) {
		printf("No memory\n");
		free(idx);
		return;
	}
	for(int i = 0; i < cnt_size; i++) cnt[i] = step;
	// Расчет
	int min = *idx[0];
	for(int i = 0; i < TEST_SIZE; i++) {
		int pos = idx[i] - data; // индекс минимального элемента в data
		 // обнуление посчитанного
		data[pos] = min;
		int cnt_pos = pos / step; // индекс счетчика
		cnt[cnt_pos]--;
		// Подсчет от начала группы
		for(int j = cnt_pos * step; j < pos; j++) {
			if(data[j] > data[pos]) res[pos]++;
		}
		// Добавление полных групп
		for(int j = 0; j < cnt_pos; j++) {
			res[pos] += cnt[j];
		}
	}
	free(cnt);
	free(idx);
	printf("Counters %s\n", t.value());
}


Время точно такое же как тут 18278951 Но кода меньше и он читабельнее.

PS Я так и не вспомнил как вывести что минимум это корень от TEST_SIZE. Математика забыта напрочь
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077174
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, теперь у меня есть с чем сравнивать свой алгоритм :)
PS


И теперь нужно подставить в исходную функцию, и получим значение функции
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077175
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Больше мы её(реализацию) никак не сократим/оптимизируем ?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077184
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryМожет быть я не так перевожу, но в англоязычной литературе встречается термин superlinear function. Скорость роста данной функции выше чем у линейной функции, например, асимптотика quick sort принадлежит классу superlinear function, и составляет . Так и тут
Возможно ее так назвали из-за внешней схожести с линейной.

...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077191
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я думаю что её так назвали потому что такой класс функций очень хорош, очень. Особенно на фоне O(n^2). А может быть тут super в смысле "выше", "больше", "сверх".
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39077224
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryБольше мы её(реализацию) никак не сократим/оптимизируем ?
В плане алгоритма нечего сокращать.

Можно return`ы поубирать, сделать вложенные if(), пару строк убавится, но имху предыдущий вариант читабельнее
Код: 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.
// С сортировкой и массивом счетчиков
void with_counter(int* data, int* res)
{
	timer t;
	int** idx = (int**)malloc(TEST_SIZE * sizeof(int*)); // индексы сортировки
	if(!idx) {
		printf("No memory\n");
	} else {
		// Заполнение индексов и сортировка
		for(int i = 0; i < TEST_SIZE; i++) idx[i] = &data[i];
		qsort(idx, TEST_SIZE, sizeof(int*), compare_int);
		// Выбор шага счетчика
		int step = (int)sqrt((double)TEST_SIZE);
		// Массив счетчиков
		int cnt_size = TEST_SIZE / step + 1;
		int* cnt = (int*) malloc(cnt_size * sizeof(int)); // счетчики
		if(!cnt) {
			printf("No memory\n");
		} else {
			for(int i = 0; i < cnt_size; i++) cnt[i] = step;
			// Расчет
			int min = *idx[0];
			for(int i = 0; i < TEST_SIZE; i++) {
				int pos = idx[i] - data; // индекс минимального элемента в data
				 // обнуление посчитанного
				data[pos] = min;
				int cnt_pos = pos / step; // индекс счетчика
				cnt[cnt_pos]--;
				// Подсчет от начала группы
				for(int j = cnt_pos * step; j < pos; j++) {
					if(data[j] > data[pos]) res[pos]++;
				}
				// Добавление полных групп
				for(int j = 0; j < cnt_pos; j++) {
					res[pos] += cnt[j];
				}
			}
			free(cnt);
		}
		free(idx);
	}
	printf("Counters %s\n", t.value());
}


Можно комментарии и скобки {} поубирать кое-где. Типа
Код: plaintext
1.
for(int j = cnt_pos * step; j < pos; j++) if(data[j] > data[pos]) res[pos]++;


Но так вообще нечитаемый изврат получится.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079303
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Версия 2.0 с деревом счетчиковИсходные данные не портит.
Код: 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.
#include <vector>
#include <algorithm>
bool compare_int_ptr(int* i,int* j) { return (*i < *j); }

// С сортировкой и деревом счетчиков
void with_counter_tree(int* data, int* res)
{
	timer t;
	// Подготовка индекса с порядком обхода
	std::vector<int*> idx(TEST_SIZE);
	for(int i = 0; i < TEST_SIZE; i++) idx[i] = &data[i];
	std::sort(idx.begin(), idx.end(), compare_int_ptr);
	// Инициализация дерева счетчиков
	std::vector<std::vector<int>> cnt_tree;
	for(int i = 2; i < TEST_SIZE; i <<= 1) {
		cnt_tree.resize(cnt_tree.size() + 1);
		cnt_tree.back().resize(TEST_SIZE / i + 1);
	}
	int cnt_levels = cnt_tree.size();
	// Расчет
	for(int i = 0; i < TEST_SIZE; i++) {
		int pos = idx[i] - data; // индекс минимального элемента в data
		res[pos] = pos;
		// подсчет кол-ва меньших data[pos]
		for(int l = 0, j = pos - 1; l < cnt_levels && j >= 0; l++) {
			j >>= 1;
			do {
				res[pos] -= cnt_tree[l][j];
				j--;
			} while((j & 1) == 0);
		}
		// увеличение счетчиков заполненных
		for(int l = 0, j = pos; l < cnt_levels; l++) {
			j >>= 1;
			cnt_tree[l][j]++;
		}
	}
	printf("Counters tree %s\n", t.value());
}


Ломал я голову как добавить дерево, пришел к мысли что массив счетчиков надо заменить на дерево счетчиков.
Смысл такой:
Строим дерево счетчиков: 0-й уровень один счетчик на 2 элемента, 1-й на 4, 2-й на 8 и т.д. пока на последнем не останется один счетчик. В итоге суммарно счетчиков столько же сколько элементов.
Вставляем на места по одному элементу исходных в порядке возрастания и по счетчикам определяем сколько уже вставлено. Затем Увеличиваем на 1 счетчики всех уровней соответствующие данному элементу.

Таким образом для подсчета с одного уровня читается не более двух счетчиков и переход на следующий уровень.
По сложности: в среднем на один элемент 1.5*log2(N/2) чтений счетчиков и log2(N/2) инкрементов.

Время расчета
ЭлементовВерсия 1.0Версия 2.01 млн.0.52 сек.0.21 сек.2 млн.1.4 сек.0.44 сек.3 млн.2.5 сек.0.66 сек.4 млн.3.78 сек.0.89 сек.8 млн.10.4 сек.1.84 сек.
Сложность улучшилась - скорость возросла.

PS Упрощать код дальше некуда. Взял <vector> чтобы читабельнее было. Если заменить на обычные массивы - будет быстрее работать в 1.5 раза, но кода для инициализации будет заметно больше.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079338
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий, спасибо. А можно пожалуйста для особо одаренных описать алгоритм по пунктам. Я не очень хорошо его понял.
PS
попытался свой алгоритм замерить по скорости, на больших значениях не получается. Вероятно что-то не так с памятью
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079357
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там две части:
1. Элементы добавляются по возрастанию их значения. Т.е. сначала минимальный, затем следующий и т.д.
Для этого надо знать в каком порядке они идут. Для этого массив idx из указателей. Массив сортируется в порядке значений по указателям.
Код который касается порядка обхода
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
void with_counter_tree_1(int* data, int* res)
{
	// Подготовка индекса с порядком обхода
	std::vector<int*> idx(TEST_SIZE);
	for(int i = 0; i < TEST_SIZE; i++) idx[i] = &data[i];
	std::sort(idx.begin(), idx.end(), compare_int_ptr);
	// Расчет
	for(int i = 0; i < TEST_SIZE; i++) {
		int pos = idx[i] - data; // индекс минимального элемента в data
		printf("insert data[%d] = %d\n", pos, data[pos]);
	}
}


Результат на твоем набореinsert data[3] = 1
insert data[4] = 3
insert data[5] = 4
insert data[1] = 5
insert data[6] = 7
insert data[9] = 8
insert data[10] = 9
insert data[7] = 11
insert data[0] = 17
insert data[2] = 18
insert data[8] = 85

Дальше исходим из аксиомы: если мы вставили значение в ячейку X то ячеек от начала с большим значением всего X-1 - количество заполненных, т.к. заполнены только с меньшими значениями.
Т.к. нумерация с нуля, то res[pos] = pos; это и есть X-1 и остается посчитать сколько уже заполнено. Тут и нужны счетчики чтобы не делать перебора до начала.

До этого места понятно расписал?

Со счетчиками хз как объяснить попроще, сейчас соображу и распишу.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079370
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Про счетчики. Давай на твоем примере из 11 значений.
Получается три уровня счетчиков. 0й 6 счетчиков, 1й - 3, 2й - 2.
Таблица как счетчики соотносятся с конкретными элементами исходного массива.
Уровень012345678910000112233445100001111222200000000111
Колонки - номера исходных элементов, строки - уровни счетчиков, тело таблицы номер счетчика данного уровня.
Если приглядишься, то увидишь что каждый счетчик нижнего уровня включает в себя ровно два счетчика верхнего. Это и есть дерево.

Значения (переменная pos) обрабатываются по одному, поэтому сначала подсчет сколько до него, затем вставка его для последущей обработки. Наоборот нельзя (вставка потом подсчет), т.к. 0й уровень для двух значений. Так же будет неправильно работать если исходный набор будет содержать повторы. Это можно полечить сделав 0й уровень для одного элемента. В нашем случае это лишняя трата памяти. Дальше в обратном порядке чтобы понятнее было.

Вставка значения:
Код: plaintext
1.
2.
3.
4.
		for(int l = 0, j = pos; l < cnt_levels; l++) {
			j >>= 1;
			cnt_tree[l][j]++;
		}


cnt_levels количество уровней.
Перебираем все слои и в каждом увеличиваем счетчик на 1. Например для вставки data[3] будут увеличены счетчики cnt_tree[0][1], cnt_tree[1][0], cnt_tree[2][0] т.е. в общем виде номер счетчика на уровне определяется по формуле pos/2^(Уровень+1)

Получения количества вставленных с начала:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
		for(int l = 0, j = pos - 1; l < cnt_levels && j >= 0; l++) {
			j >>= 1;
			do {
				res[pos] -= cnt_tree[l][j];
				j--;
			} while((j & 1) == 0);
		}


берем pos-1 находим для него счетчик нулевого уровня, если начало счетчика не совпадает с началом счетчика следующего уровня, то берем предыдущий счетчик, начала уровней совпало - переходим на уровень выше и берем там предыдущий и т.д.
Например для подсчета сколько перед data[7] складываем cnt_tree[0][3]+cnt_tree[0][2]+cnt_tree[1][0]
для data[8] можно сразу взять cnt_tree[2][0], но у меня посчитается cnt_tree[0][3]+cnt_tree[0][2]+cnt_tree[1][0]
data[9] будет cnt_tree[0][4]+cnt_tree[1][1]+cnt_tree[1][0] хотя можно было cnt_tree[0][4]+cnt_tree[2][0]
Небольшой задел для оптимизации есть :)

Принцип понятен?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079388
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury,

я вот читал-читал, а вы сделать-то что пытаетесь?
функциональный аналог массива делается на весо-сбалансированных бинарных деревьях, вставка-удаление O(log(N)), поиск элемента по номеру тоже на них легко делается - O(log(N))

если нужно по-быстрому, то на декартовых с поддержкой агрегации

но тот же массив на малых объёмах проигрывает обычному - за исключенеим случаев массовых операций
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079437
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tдля data[8] можно сразу взять cnt_tree[2][0], но у меня посчитается cnt_tree[0][3]+cnt_tree[0][2]+cnt_tree[1][0]
data[9] будет cnt_tree[0][4]+cnt_tree[1][1]+cnt_tree[1][0] хотя можно было cnt_tree[0][4]+cnt_tree[2][0]
Небольшой задел для оптимизации есть :)
Поправил. Не зря расписывал, сам лучше понял как работает. Теперь 8 млн. за 1.59 сек. (было 1.84 сек.)
Версия 2.1
Код: 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.
#include <vector>
#include <algorithm>
bool compare_int_ptr(int* i,int* j) { return (*i < *j); }
// С сортировкой и деревом счетчиков
void with_counter_tree(int* data, int* res)
{
	timer t;
	// Подготовка индекса с порядком обхода
	std::vector<int*> idx(TEST_SIZE);
	for(int i = 0; i < TEST_SIZE; i++) idx[i] = &data[i];
	std::sort(idx.begin(), idx.end(), compare_int_ptr);
	// Инициализация дерева счетчиков
	std::vector<std::vector<int>> cnt_tree;
	for(int i = 2; i < TEST_SIZE; i <<= 1) {
		cnt_tree.resize(cnt_tree.size() + 1);
		cnt_tree.back().resize(TEST_SIZE / i + 1);
	}
	int cnt_levels = cnt_tree.size();
	// Расчет
	for(int i = 0; i < TEST_SIZE; i++) {
		int pos = idx[i] - data; // индекс минимального элемента в data
		res[pos] = pos;
		// подсчет кол-ва меньших data[pos]
		for(int l = 0, j = pos - 1; l < cnt_levels && j >= 0; l++) {
			j >>= 1;
			if((j & 1) == 0) {
				res[pos] -= cnt_tree[l][j];
				j--;
			};
		}
		// увеличение счетчиков заполненных
		for(int l = 0, j = pos; l < cnt_levels; l++) {
			j >>= 1;
			cnt_tree[l][j]++;
		}
	}
	printf("Counters tree %s\n", t.value());
}

...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079462
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)SashaMercury,

я вот читал-читал, а вы сделать-то что пытаетесь?
Тут Саша человеческим языком писал 18265745 Наиболее точно ТЗ описывает этот пост
SashaMercuryЕсли упростить задачу, то у нас есть неупорядоченный массив с уникальными элементами. Для каждого элемента мне нужно определить сколько элементов до него(слева от него) больше него
Есть уточнения.
SashaMercuryникакие элементы в список не добавляются. Один раз добавятся и всё. Дальше будут только удаляться. В цикле. На каждой итерации цикла мне нужно искать минимальный элемент и мне необходимо узнать сколько элементов от него слева. Удаляю этот элемент и проделываю аналогичные действия. Итерации продолжаются пока есть элементы
kealon(Ruslan)функциональный аналог массива делается на весо-сбалансированных бинарных деревьях, вставка-удаление O(log(N)), поиск элемента по номеру тоже на них легко делается - O(log(N))
Про деревья в том топике предлагали. Я не большой знаток деревьев, точнее теорию знаю, реально ни разу не использовал. Все пытаюсь понять как решать деревом эту задачу. Даже если мы в каждом узле будем хранить сколько в его окончаниях листьев, то все равно потребуется обход достаточно большого количества узлов чтобы посчитать сколько листьев перед свеже вставленным. Заметно больше чем log2(n)
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079487
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, это дерево отрезков, классическя олимпиадная задачка,
в кажом узле дерева хранится min, max и количество элементов в дереве
SashaMercuryЗдравствуйте.
Подскажите пожалуйста, существует ли структура данных(организована линейно) со следующими характеристиками:
1. Поиск индекса минимального/максимального элемента

поиск O(Log(N))
SashaMercury2. Удаление элемента

вставка-удаление O(Log(N))

Dima TПро деревья в том топике предлагали. Я не большой знаток деревьев, точнее теорию знаю, реально ни разу не использовал. Все пытаюсь понять как решать деревом эту задачу. Даже если мы в каждом узле будем хранить сколько в его окончаниях листьев, то все равно потребуется обход достаточно большого количества узлов чтобы посчитать сколько листьев перед свеже вставленным. Заметно больше чем log2(n)
не больше, завтра постараяюсь написать, к сожалению времени в последнее время особо нет
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079500
Владимир2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryМне, вообще говоря, интересна 2 постановкаСаша вы молодец!
Очень интересно было бы посмотреть /поучаствовать/ в дискуссиях:

- виды деревьев, применимость их и способы представления в памяти и на диске;

- форматы данных и способы их представления в памяти и на диске.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079502
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)не больше, завтра постараяюсь написать, к сожалению времени в последнее время особо нет
Не забудь. Интересно. Обещаю затестить в равных условиях со своими поделками.
Я тут заготовку для тестов давал 18274025
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079507
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryМожет быть я не так перевожу, но в англоязычной литературе встречается термин superlinear function. Скорость роста данной функции выше чем у линейной функции, например, асимптотика quick sort принадлежит классу superlinear function, и составляет . Так и тут
Роберт Седжвик пишет об этой функции
N Log N - Время выполнения, пропорциональное N log N имеет место когда алгоритм
решает задачу разбивая ее на подзадачи меньших размеров, решая их независимо и затем
объединяя решения. Из за отсутствия подходящего прилагательного ("линерифмический" -
linerihmic ?) мы просто говорим что время выполнения такого алгоритма равно N log N.
Когда N равно 1000 000, N log N возрастает примерно до 20 млн. Когда N удваивается
то время N log N возрастает более чем вдвое (но не намного более).
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079593
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan) я вот читал-читал, а вы сделать-то что пытаетесь?

В первом посте этого топика отправил код. Продублирую
Код: 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>

struct node
{
	int value;//key
	int counter;//number of elements in the tree over then current at time of adding
	int counter_r;//number of elements right subtree
	node *left, *right;
	void print();
};

void node::print()
{
	printf("%i %i %i   \n", value, counter_r, counter);
}

class tree
{
	node* root;
	int measure;
	void insert(node*& n, int v, int c);
	void print(node* n);
	void measure_calculate(node* n);
public:
	tree();
	tree(int* a, size_t n);
	void print();
	void measure_calculate();
	int measure_get();
};

tree::tree()
{
	root = NULL;
	measure = 0;
}

tree::tree(int* a, size_t n)
{
	root = NULL;
	measure = 0;
	for (int i = 0; i < n; ++i){
		this->insert(root, a[i], 0);
	}
}

void tree::insert(node*& n, int v, int c)
{
	node* cur;
	if (n == NULL){
		cur = (node*)malloc(sizeof(node)* 1);
		cur->value = v;
		cur->left = NULL;
		cur->right = NULL;
		cur->counter_r = 0;
		cur->counter = c;
		n = cur;
	}
	else{
		if (n->value > v){
			this->insert(n->left, v, c + n->counter_r + 1);
		}
		else{
			n->counter_r += 1;
			this->insert(n->right, v, c);
		}
	}
}

void tree::print()
{
	print(root);
}

void tree::print(node* n)
{
	if (n){
		print(n->left);
		n->print();
		print(n->right);
	}
}


void tree::measure_calculate()
{
	measure_calculate(root);
}

void tree::measure_calculate(node* n)
{
	if (n){
		measure_calculate(n->left);
		measure += n->counter;
		measure_calculate(n->right);
	}
}

int tree::measure_get()
{
	return measure;
}


int main()
{
	int b[11] = { 17, 5, 18, 1, 3, 4, 7, 11, 85, 8, 9 };
	tree t(b, 11);
	t.measure_calculate();
	printf("%i\n", t.measure_get());
	return 0;
}
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079598
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima_Tберем pos-1 находим для него счетчик нулевого уровня, если начало счетчика не совпадает с началом счетчика следующего уровня, то берем предыдущий счетчик, начала уровней совпало - переходим на уровень выше и берем там предыдущий и т.д.
Например для подсчета сколько перед data[7] складываем cnt_tree[0][3]+cnt_tree[0][2]+cnt_tree[1][0]
для data[8] можно сразу взять cnt_tree[2][0], но у меня посчитается cnt_tree[0][3]+cnt_tree[0][2]+cnt_tree[1][0]
data[9] будет cnt_tree[0][4]+cnt_tree[1][1]+cnt_tree[1][0] хотя можно было cnt_tree[0][4]+cnt_tree[2][0]
Небольшой задел для оптимизации есть :)

Принцип понятен?
Мне кажется что данный алгоритм аналогичен алгоритму выше. Только у меня дерево фигурирует явно, а у тебя нет. Если я всё правильно понял
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079632
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryМне кажется что данный алгоритм аналогичен алгоритму выше. Только у меня дерево фигурирует явно, а у тебя нет. Если я всё правильно понял
Потестил твой код на скорость.
ЭлементовДерево (сек.)Версия 2.1 (сек.)100 тыс.0.070.02200 тыс.0.270.04400 тыс.0.390.07800 тыс.4.230.141600 тыс.3.730.31
Смотрим не на время, а на скорость прироста в разах. Твой растет быстрее и как-то неравномерно.
Вот еще замер, от количества элементов зависит как они перемешаются.
ЭлементовДерево (сек.)Версия 2.1 (сек.)8000004.230.148000011.950.148000021.420.148000031.850.14
Деревья могут вырождаться, тогда производительность от их использования резко падает. Похоже это твой это случай. Не могу точно сказать, как выше писал не силен в деревьях.

Как минимум у тебя в коде надо оптимизировать выделение памяти. malloc() для каждого элемента - это не быстро. Сколько элементов будет в итоге примерно известно. Выдели сразу кусок памяти и выдавай оттуда по одному элементу, кончится - еще кусок.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079638
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Исправил C:
Код: 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.
#include <stdio.h>
#include <stdlib.h>

struct node
{
	int value;//key
	int counter;//number of elements in the tree over then current at time of adding
	int counter_r;//number of elements right subtree
	node *left, *right;
	void print();
};

void node::print()
{
	printf("%i %i %i   \n", value, counter_r, counter);
}

class tree
{
	node* root;
	int measure;
	node* buf;
	void insert(node*& n, int v, int c, size_t num_buf);
	void print(node* n);
	void measure_calculate(node* n);
public:
	tree();
	tree(int* a, size_t n);
	void print();
	void measure_calculate();
	int measure_get();
};

tree::tree()
{
	root = NULL;
	measure = 0;
	buf = NULL;
}

tree::tree(int* a, size_t n)
{
	root = NULL;
	measure = 0;
	buf = (node*)malloc(sizeof(node)*n);
	for (int i = 0; i < n; ++i){
		this->insert(root, a[i], 0, i);
	}
}

void tree::insert(node*& n, int v, int c, size_t num_buf)
{
	node* cur=buf+num_buf;
	if (n == NULL){
		cur->value = v;
		cur->left = NULL;
		cur->right = NULL;
		cur->counter_r = 0;
		cur->counter = c;
		n = cur;
	}
	else{
		if (n->value > v){
			this->insert(n->left, v, c + n->counter_r + 1, num_buf);
		}
		else{
			n->counter_r += 1;
			this->insert(n->right, v, c, num_buf);
		}
	}
}

void tree::print()
{
	print(root);
}

void tree::print(node* n)
{
	if (n){
		print(n->left);
		n->print();
		print(n->right);
	}
}


void tree::measure_calculate()
{
	measure_calculate(root);
}

void tree::measure_calculate(node* n)
{
	if (n){
		measure_calculate(n->left);
		measure += n->counter;
		measure_calculate(n->right);
	}
}

int tree::measure_get()
{
	return measure;
}


int main()
{
	int b[11] = { 17, 5, 18, 1, 3, 4, 7, 11, 85, 8, 9 };
	tree t(b, 11);
	t.measure_calculate();
	printf("%i\n", t.measure_get());
	return 0;
}

...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079651
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стало быстрее
ЭлементовДерево 1.0 (сек.)Дерево 1.1 (сек.)8000004.232.998000011.951.328000021.420.908000031.851.25
Но неравномерность не исчезла. Надо алгоритм допиливать.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079739
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryМне кажется что данный алгоритм аналогичен алгоритму выше. Только у меня дерево фигурирует явно, а у тебя нет. Если я всё правильно понял
Почитал немного про деревья. Думаю разница именно в сбаллансированности дерева. Классическое дерево при наполнении вырождается, поэтому есть более продвинутые алгоритмы чтобы этого избегать: АВЛ-дерево , Красно-чёрное дерево

Там упоминают
... контейнеры set и map в большинстве реализаций библиотеки STL языка C++[2], класс TreeMap языка Java[3], так же, как и многие другие реализации ассоциативного массива в различных библиотеках, основаны на красно-чёрных деревьях.


Думаю отсюда можно предположить что заполнение std::set будет примерно таким же по времени как и при решении твоей задачи. Т.е. считаем что std::set это идеально реализованное дерево.
Затестил такой код
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
#include <set>
void with_set(int* data, int* res)
{
	timer t;
	std::set<int> tree;
	tree.get_allocator().allocate(TEST_SIZE);
	for(int i = 0; i < TEST_SIZE; i++) {
		// добавляем элемент
		tree.insert(data[i]);
	}
	printf("Fill tree %s\n", t.value());
	timer t2;
	tree.clear();
	printf("Clear tree %s\n", t2.value());
}


Результаты
ЭлементовДерево 1.0 (сек.)Дерево 1.1 (сек.)Fill setClear set8000004.232.990.437.48000011.951.320.433.678000021.420.900.420.428000031.851.250.433.13
Скорость заполнения стабильная, но все тормоза почему-то перешли на очистку. Причем общее время пропорционально твоему. Интересно. Похоже MS коряво очистку реализовал. Надо в линуксе потестить.

PS Ты в своем коде освобождение памяти забыл добавить.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079747
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TДеревья могут вырождаться, тогда производительность от их использования резко падает. Похоже это твой это случай. Не могу точно сказать, как выше писал не силен в деревьях. Могут, если не балансировать. Пока не сделаешь сбалансированное дерево проводить измерения времени нет смысла. Результат будет сильно зависеть от исходных данных.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39079774
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T Похоже MS коряво очистку реализовал. Надо в линуксе потестить.
Разобрался. Из-за отладчика у МС тормоза даже при запуске в релизе. Позапускал просто exe. Нет тормозов.
Заполнение стабильно 0.13 сек. Очистка 0.07 сек. Мой код в обоих вариантах 0.14 сек.

Потестил в линуксе. Железо тоже самое. Компилятор g++ 4.7.2
Заполнение 800 тыс. в std::set стабильно 0.07 сек, очистка 0.02 сек. Мой код даже чуть дольше виндового варианта 0.17 сек.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080021
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо.
Попробую поправить
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080598
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
привет всем
понял теперь вашу задачку

Index любого элемента так просто не найдёшь, это да

Dima T, тут что-то хитрее надо
на постоянном массиве достаточно "пронумеровать" массив и отсортировать этот индекс по значению
быстрее чем дерево будет

SashaMercury, а элементы действительно нужно удалять и вставлять?
может саму задачу скажешь зачем тебе такая структура?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080610
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)Dima T, тут что-то хитрее надо
ИМХУ Сашино дерево из первого поста взлетит если балансировку добавить.
kealon(Ruslan)на постоянном массиве достаточно "пронумеровать" массив и отсортировать этот индекс по значению
быстрее чем дерево будет
Разверни свою мысль поподробней. Как пронумеровать? Я тоже об этом думал. Ничего не придумал.

kealon(Ruslan)SashaMercury, а элементы действительно нужно удалять и вставлять?
может саму задачу скажешь зачем тебе такая структура?
На 99% уверен что задачка академическая из серии олимпиадных. Саша несколько задач отсюда уже выносил на местное обсуждение.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080748
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)на постоянном массиве достаточно "пронумеровать" массив и отсортировать этот индекс по значению
быстрее чем дерево будет
положим, у нас массив уже упорядочен. Что нам даст нумерация его элементов?

Номер элемента совпадает с индексом, значит слева нет "лишних" элементов.

Пусть в исходном массиве первый элемент не на своем месте. После сортировки он встанет на место n, а элементы от 2 до n сдвинутся. У этих элементов номер будет на 1 больше индекса. У переставленного элемента номер 1 на n меньше индекса n+1. Остальные элементы остались на своих местах.

Только сложность алгоритма быстрой сортировки может достигать О(N*N).
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080764
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прочитал статью Тадао Такаока(учёный не так давно решивший новым способом проблему Maimum subarray sum) о новых мерах энтропии неупорядоченного массива, захотел посмотреть алгоритмы работы со старыми. Информации особой по реализации не нашёл, потому решил самостоятельно этим заняться
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080784
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabkealon(Ruslan)на постоянном массиве достаточно "пронумеровать" массив и отсортировать этот индекс по значению
быстрее чем дерево будет
положим, у нас массив уже упорядочен. Что нам даст нумерация его элементов?

Номер элемента совпадает с индексом, значит слева нет "лишних" элементов.

Пусть в исходном массиве первый элемент не на своем месте. После сортировки он встанет на место n, а элементы от 2 до n сдвинутся. У этих элементов номер будет на 1 больше индекса. У переставленного элемента номер 1 на n меньше индекса n+1. Остальные элементы остались на своих местах.

в индексе будут позиции элементов в исходном массиве
Код: pascal
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.
program test2;

const
  TEST_SIZE = 50000;

type
  TValue = integer;
  TIndexArray = array of integer;
var
  Arr: array of TValue;


  procedure Init;
  var
    i: integer;
    tmp: TValue;
    r: integer;
  begin
    for i := 0 to TEST_SIZE - 1 do
      arr[i] := i;
    // Перемешиваем
    r := 54323; // ГСЧ с постоянной последовательстью
    for i := 0 to TEST_SIZE - 1 do
    begin
      repeat
        r := (r * 12347 + 1) mod TEST_SIZE;
      until (r >= 0);

      tmp := arr[i];
      arr[i] := arr[r];
      arr[r] := tmp;
    end;
  end;

  procedure QuickSort(FList: PInteger; L, R: longint);

    function Compare(a, b: integer): integer;
    begin
      Result := Arr[a] - Arr[b];
    end;

  var
    I, J: longint;
    P, Q: integer;
  begin
    repeat
      I := L;
      J := R;
      P := FList[(L + R) div 2];
      repeat
        while Compare(P, FList[i]) > 0 do
          I := I + 1;
        while Compare(P, FList[J]) < 0 do
          J := J - 1;
        if I <= J then
        begin
          Q := FList[I];
          Flist[I] := FList[J];
          FList[J] := Q;
          I := I + 1;
          J := J - 1;
        end;
      until I > J;
      // sort the smaller range recursively
      // sort the bigger range via the loop
      // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
      if J - L < R - I then
      begin
        if L < J then
          QuickSort(FList, L, J);
        L := I;
      end
      else
      begin
        if I < R then
          QuickSort(FList, I, R);
        R := J;
      end;
    until L >= R;
  end;

  procedure SearchIndexes(var m: TIndexArray);
  var
    i: integer;
  begin
    for i := 0 to TEST_SIZE - 1 do
      m[i] := i;
    QuickSort(@m[0], 0, TEST_SIZE - 1);

  end;

var
  m: TIndexArray;
begin
  SetLength(Arr, TEST_SIZE);
  Init;
  SetLength(m, TEST_SIZE);
  SearchIndexes(m);
  for i:=0 to 6 do
  begin
    Writeln('Element:',Arr[m[i]], '  position:',m[i],
    '  smaller count:', i,'  greater count:', TEST_SIZE-i-1);
  end;    
end.


Код: plaintext
1.
2.
3.
4.
5.
6.
Element:0  position:5000  smaller count:0  greater count:49999
Element:1  position:5001  smaller count:1  greater count:49998
Element:2  position:9452  smaller count:2  greater count:49997
Element:3  position:8635  smaller count:3  greater count:49996
Element:4  position:5004  smaller count:4  greater count:49995
Element:5  position:11505  smaller count:5  greater count:49994
Element:6  position:9530  smaller count:6  greater count:49993
mcureenabТолько сложность алгоритма быстрой сортировки может достигать О(N*N).
вообще-то всегда O(N*Log(N))
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080785
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПрочитал статью Тадао Такаока(учёный не так давно решивший новым способом проблему Maimum subarray sum) о новых мерах энтропии неупорядоченного массива, захотел посмотреть алгоритмы работы со старыми. Информации особой по реализации не нашёл, потому решил самостоятельно этим заняться
ох уж эти японцы, суровые ребята - чуть мозг не поломал пока весо-сбалансированное дерево делал (тоже японцы придумали)

только как к теме вопроса относится "Maximum subarray sum" ?
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080801
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)в индексе будут позиции элементов в исходном массиве
Код: plaintext
1.
2.
3.
Element:0  position:5000  smaller count:0  greater count:49999
Element:1  position:5001  smaller count:1  greater count:49998
Element:2  position:9452  smaller count:2  greater count:49997
...

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

У меня первая мысль была что можно отсортировать, а затем как-то в один проход посчитать используя только 2 индекса элемента: в изначальном массиве и отсортированном. Но запнулся на такой последовательности 1,5,3,2,4. Результат у нее 0+0+1+2+1.

ЗЫ про С/С++ форум. Паскаль запустить негде. Тут заготовка теста с перебором 18274025
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080803
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПрочитал статью Тадао Такаока(учёный не так давно решивший новым способом проблему Maimum subarray sum) о новых мерах энтропии неупорядоченного массива, захотел посмотреть алгоритмы работы со старыми. Информации особой по реализации не нашёл, потому решил самостоятельно этим заняться
Там критично именно так считать? Может взять за основу что-нибудь близкое, но легче считаемое? Например получить сумму смещений вперед после сортировки.
Например:
1,5,3,2,4 исходный
1,2,3,4,5 отсортированный
тут только 5 уехало на 3 вперед, т.е. итого 3.
Это быстрее считается.
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080892
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В случае если многократного 'неудачного выбора' опорной точки асимптотика quicksort будет О(n^2).

Maximum subarray sum известная задача, в отличие от меры упорядоченности массива. Потому я думал по ней все поймут кто этот японец
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080896
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TSashaMercuryПрочитал статью Тадао Такаока(учёный не так давно решивший новым способом проблему Maimum subarray sum) о новых мерах энтропии неупорядоченного массива, захотел посмотреть алгоритмы работы со старыми. Информации особой по реализации не нашёл, потому решил самостоятельно этим заняться
Там критично именно так считать? Может взять за основу что-нибудь близкое, но легче считаемое? Например получить сумму смещений вперед после сортировки.
Например:
1,5,3,2,4 исходный
1,2,3,4,5 отсортированный
тут только 5 уехало на 3 вперед, т.е. итого 3.
Это быстрее считается.

там вообще не так считают и не совсем про это, больше теорем)) Мне захотелось посчитать меру таким образом(скорее всего так тоже считают, и мы тут не первооткрыватели ), но аналогичных расчётов я не нашёл в сети. В России этим очевидно никто не занимается, а зарубежных статей не много. Тем более все статьи из журналов SIAM платные. Потому 'погуглить'(как мне обычно советует Анатолий) не получилось
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39080969
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryПодскажите пожалуйста в чём главные ошибки по реализации программы в оос. И может быть у кого-то есть ещё соображения по реализации алгоритма (с линейной скоростью или с лучшей организацией дерева за исключением вопросов балансировки(на данный момент))

PS
Я ещё не прочитал статью о различиях между malloc и new потому пока использую malloc, вы в своих программах на С++ используете только new ?

Память лучше выделять большими блоками, чтобы кучу лишний раз не дергать и расход меньше:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
--
const size_t BLOCK_SIZE = 1024;
struct node * g_block_nodes;
size_t g_block_free = 0;

...


if(!block_free)
{
    block_nodes = calloc(sizeof(struct node[BLOCK_SIZE]));
    block_free = BLOCK_SIZE;
}
struct node * l_node = block_nodes[--block_free];
...
Рейтинг: 0 / 0
Мера неупорядоченности линейного массива и некоторые вопросы
    #39081500
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tkealon(Ruslan)в индексе будут позиции элементов в исходном массиве
Код: plaintext
1.
2.
3.
Element:0  position:5000  smaller count:0  greater count:49999
Element:1  position:5001  smaller count:1  greater count:49998
Element:2  position:9452  smaller count:2  greater count:49997
...

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

У меня первая мысль была что можно отсортировать, а затем как-то в один проход посчитать используя только 2 индекса элемента: в изначальном массиве и отсортированном. Но запнулся на такой последовательности 1,5,3,2,4. Результат у нее 0+0+1+2+1.

ЗЫ про С/С++ форум. Паскаль запустить негде. Тут заготовка теста с перебором 18274025
ну тогда с весо-балансированным деревом легко решается
Код: pascal
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.
program TestWeightBalance;

uses GUtils,OrdSets;

const
  TEST_SIZE = 50000;

type
  TValue = integer;
var
  Arr: array of TValue;


  procedure Init;
  var
    i: integer;
    tmp: TValue;
    r: integer;
  begin
    for i := 0 to TEST_SIZE - 1 do
      arr[i] := i;
    // Перемешиваем
    r := 54323; // ГСЧ с постоянной последовательстью
    for i := 0 to TEST_SIZE - 1 do
    begin
      repeat
        r := (r * 12347 + 1) mod TEST_SIZE;
      until (r >= 0);

      tmp := arr[i];
      arr[i] := arr[r];
      arr[r] := tmp;
    end;
  end;
type
  TUp=Specialize GUp<TValue>;
  TValueSet=specialize OrdSetWB <TValue,TUp>;

var

  i,p: integer;
  vs: TValueSet;
begin
  SetLength(Arr, TEST_SIZE);
  Init;
  vs:=TValueSet.Create;
  try
    for i:=0 to TEST_SIZE-1 do begin
      vs.Insert(arr[i]);
      p := vs.KeyIndex(arr[i]);
      writeln('< Count:', p, '  >Count:', i - p);
    end;
  finally
    vs.Free;
  end;
end.



реп с либами здесь


компилируется только под Lazarus (fpc)
...
Рейтинг: 0 / 0
53 сообщений из 53, показаны все 3 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Мера неупорядоченности линейного массива и некоторые вопросы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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