<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Два студента пишут лабы &#187; Теория алгоритмов</title>
	<atom:link href="http://www.studcode.ru/archiv/category/konspekty/teoriya/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.studcode.ru</link>
	<description>Конспекты лекций, самостоятельные работы по  delphi, с++, php. Курсовые проекты. Все что мы сделали вы можете скачать без проблем!</description>
	<lastBuildDate>Wed, 27 Oct 2010 15:15:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Коллекции</title>
		<link>http://www.studcode.ru/archiv/kollekcii/</link>
		<comments>http://www.studcode.ru/archiv/kollekcii/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:57:07 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=492</guid>
		<description><![CDATA[Понятие коллекции. Классификация
Коллекции представляют собой организацию данных и определяют методы доступа к этим данным. Коллекции подразделяются на две категории: линейные и нелинейные. Линейная коллекция содержит список элементов, упорядоченных по положению. В этом списке имеется первый элемент, второй и т.д. Массив с индексом, отражающим порядок элементов является основным примером линейной коллекции. Нелинейная коллекция определяет элементы без [...]]]></description>
			<content:encoded><![CDATA[<h2>Понятие коллекции. Классификация</h2>
<p><em>Коллекции</em> представляют собой организацию данных и определяют методы доступа к этим данным. Коллекции подразделяются на две категории: линейные и нелинейные. <em>Линейная</em> коллекция содержит список элементов, упорядоченных по положению. В этом списке имеется первый элемент, второй и т.д. Массив с индексом, отражающим порядок элементов является основным примером линейной коллекции. <em>Нелинейная</em> коллекция определяет элементы без позиционного упорядочивания. С помощью прямого доступа мы можем выбрать элемент непосредственно, не обращаясь к предыдущим. Примером такой коллекции служит уже хорошо знакомый нам массив, для доступа к элементам которого мы можем использовать индексы. В коллекциях, называемых последовательными списками прямой доступ невозможен. Нужно сперва обратиться к первому элементу, затем через него ко второму и т.д. до нужного.<br />
<span id="more-492"></span></p>
<h2>Коллекции с индексным доступом</h2>
<p>К данному виду относят словари и хеш-таблицы.</p>
<p><em>Хеш-таблица</em> &#8211; коллекция, в которой имеется набор ключей и связанных с каждым ключом данных. Поиск и выборка данных осуществляется по ключу, который трансформируется в целый индекс, используемый для нахождения данных.</p>
<p><em>Словарь</em> &#8211; разновидность хеш-таблицы, в которой ключом выступает слово, а значением &#8211; строка, указывающая его определение. К значению осуществляется прямой доступ с использованием ключа в качестве индекса. В результате словарь подобен массиву, за исключением того, что индексы не должны быть целыми числами. Словари также часто называют ассоциативными массивами.</p>
<h2>Коллекции с прямым доступом</h2>
<p><em>Массив</em> &#8211; совокупность однотипных элементов, расположенных в смежных ячейках памяти. Для доступа к элементам используют числовой индекс &#8211; порядковый номер в наборе.</p>
<p><em> Запись</em> &#8211; это базовая структура коллекций для сохранения данных, которые могут состоять из разных типов. Для многих программ различные элементы данных ассоциированы с одним объектом. Например авиабилет включает такие данные, как номер рейса, номер места, имя пассажира, стоимость. Запись связывает поля структуры данных при обеспечении прямого доступа к данным в отдельных полях.</p>
<h2>Коллекции с последовательным доступом</h2>
<p>Более общей коллекцией является <em>список</em>, сохраняющий элементы в определенном порядке. Структура, называемая линейным списком содержит произвольное число элементов. Размер списка изменяется, после удаления и добавления к нему новых элементов. Первый элемент находится в начале или голове списка, а последний &#8211; в хвосте списка. Каждый элемент списка имеет связь с последующим, таким образом можно передвигаться от одного элемента к другому. Для доступа к элементам списка необходимо выполнять прохождение от головы до нужной позиции. Если движение по списку можно осуществлять только в одном направлении, то список называется <em>однонаправленным</em>, если в двух направлениях &#8211; <em>двунаправленный</em>. Если элемент списка хранит информацию об одном &#8220;соседе&#8221;, то список называется <em>односвязным</em>, если о двух &#8211; <em>двусвязным</em>.</p>
<p><em>Стеки и очереди</em> &#8211; особые версии линейного списка с ограниченным доступам к элементам данных. В стеке элементы добавляются и удаляются через один конец списка, называемым вершиной. Операция удаления элемента называется извлечением из стека, операция добавления называется помещением элемента в стек. При помещении элемента в стек все остальные элементы опускаются вниз, уступая место на вершине новому элементу. Когда элемент удаляется, остальные перемещаются в обратном порядке. Последний элемент, помещенный в стек, является первым извлекаемым.</p>
<p><em>Очередь</em> &#8211; это список с доступом в начало и конец. Элементы вставляются в конец, а извлекаются из начала списка. Иногда используются очереди приоритетов. В них добавление новых элементов происходит в конец, а удаление &#8211; из произвольного места согласно приоритету.</p>
<p>В машинной системе<em> файл</em> &#8211; это коллекция, имеющая ассоциированную структуру данных, называемую потоком и представляющая собой последовательность байт, связанная с внешним устройствам с помощью потока, через который осуществляется обмен информацией с устройством.</p>
<h2>Нелинейные коллекции</h2>
<p><em>Иерархическая коллекция</em> &#8211; набор элементов, разделенных на уровни. Элементны на текущем уровне могут иметь несколько связанных элементов на нижнем уровне. Особой иерархической коллекцией является <em>дерево</em>, в которой на верхнем уровне имеется один эелемент &#8211; <em>корень</em>. Элементы в дереве называют <em>узлами</em>, каждый из которых указывает на нисходящие узлы, называемыми <em>потомками</em>. Каждый элемент, за исключением корня имеет одного потомка. Дерево является идеальной структурой для описания файловой системы с каталогами и подкаталогами.</p>
<p><em>Группа</em> &#8211; представляет те коллекции, которые содержат элементы без упорядочивания. Набор переменных в программе &#8211; яркий пример группы. Сюда можно отнести <em>граф</em> &#8211; структуру, задающую набор вершин и набор связей, соединяющих вершины. Графы широко используются в планировании, транспортных задачах и в задачах проектирования. <em>Сеть</em> &#8211; особая форма графа, которая приписывает вес каждой связи. Вес указывает стоимость использования связи при прохождения графа. Так в задаче коммивояжера используется сеть для представления городов и стоимостей проезда из города в город.</p>
<h2>Программная реализация списков</h2>
<p>Рассмотрев классификацию коллекций приступим к практической их реализации. Начнем с общих вопросов. Список может храниться в памяти двумя способами. Во-первых, это традиционное последовательное расположение элементов с смежных областях памяти, а во-вторых, в произвольных областях с динамическими связями между собой. Основным преимуществом динамически связанных списков является простота изменения порядка следования элементов. В массиве для изменения порядка мы вынуждены делать перестановку элементов, что отнимает время и приводит к массе ненужных операций. С ростом размера элемента и их числа эти факторы сильно влияют на выполнение программы. В динамическом списке нет необходимости перемещать элементы, важно только изменить адресные связи. Для организации списка нам необходимы динамические объекты, расположенные в любых областях памяти и связанных между собой через адреса. Элемент списка должен содержать информационные поля для хранения данных и служебные поля для хранения адресов связанных с ним элементов. В языках программирования используются составные типы, которые могут включать несколько полей с данными. Для хранения адресов используются специальные переменные указатели. Таким образом, для реализации элемента списка нам потребуются составной тип и указатели.</p>
<pre><code>
struct Item
{
		char *text;     // информационные поля
		Item *next;    // служебные поля
};</code></pre>
<p>Рассмотрим программные реализации общих для односвязного списка операций:<br />
СОЗДАНИЕ ПЕРВОГО ЭЛЕМЕНТА<br />
<code> </code></p>
<pre>Item *unit(char *str)
{
	Item *head=new Item;
	head-&gt;text=new char[strlen(str)+1];
	strcpy(head-&gt;text,str);
	head-&gt;next=NULL;
	return head;
}</pre>
<p>ДОБАВЛЕНИЕ ЭЛЕМЕНТА (в голову n = 0)<br />
<code> </code></p>
<pre>Item *addItemNOM(Item *head,char *buf,int n)
{
	Item *temp=head;
	Item *item=new Item;
	item-&gt;text=new char[strlen(buf)+1];
	strcpy(item-&gt;text,buf);
	if(n==0)
	{
		item-&gt;next=head;
		return item;
	}
	else
	{
		for(int i=1;i&lt;(n-1) &amp;&amp; head-&gt;next;i++)
			head=head-&gt;next;
		item-&gt;next=head-&gt;next;
		head-&gt;next=item;
		return temp;
	};
}</pre>
<p>УДАЛЕНИЕ ЭЛЕМЕНТА<br />
<code> </code></p>
<pre>Item *removeItemNOM(Item *head,int n)
{
	Item *temp=head,*item=0;
	if(n==0)
	{
		head=head-&gt;next;
		delete temp;
		return head;
	}
	else
	{
		for(int i=1;inext-&gt;next;i++)
			head=head-&gt;next;
		item=head-&gt;next;
		head-&gt;next=head-&gt;next-&gt;next;
		delete item;
		return temp;
	};
}</pre>
<p>УДАЛЕНИЕ СПИСКА<br />
<code> </code></p>
<pre>bool removeALL(Item *head)
{
	if(!head) return false;
	Item *temp;
	while (head)
	{
		temp=head-&gt;next;
		delete head;
		head=temp;
	}
	return true;
}</pre>
<p>СОХРАНЕНИЕ СПИСКА<br />
<code> </code></p>
<pre>void saveall(Item *head,FILE *fp)
{
while(1)
{
fwrite(head,sizeof(Item),1,fp);
if(head-&gt;next)
head=head-&gt;next;
else
return;
}
}</pre>
<p>ЗАГРУЗКА СПИСКА ИЗ ФАЙЛА<br />
<code> </code></p>
<pre>Item  * loadall(Item *head,FILE *fp)
{
fseek(fp,0L,0);
head=new Item; int a;
BOOK *old_head=head,*temp;
while((a=fread(head,sizeof(Item),1,fp)))
{
head-&gt;next=new Item;
temp=head;
head=head-&gt;next;
}
head=temp;
head-&gt;next=NULL;
return old_head;
}</pre>
<p>КОПИРОВАНИЕ СПИСКА<br />
<code> </code></p>
<pre>Item  * copy(Item  * head1, Item  * head2)
{
head2=new Item;
Item  * old_head2=head2;
while(1)
{
memcpy(head2,head1,sizeof(Item));
if(head1-&gt;next)
{
head2-&gt;next=new Item;
head1=head1-&gt;next;
head2=head2-&gt;next;
}
else
break;
}
head2-&gt;next=NULL;
return old_head2;
}
ПОИСК ПО ПОЛЮ
Item *search_title(Item  * head,char  * text)
{
while(head-&gt;next)
{
if(!strcmp(head-&gt; text, text)) return head;
head=head-&gt;next;
}
if(!strcmp(head-&gt; text, text))
return head;
else
return NULL;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/kollekcii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Алгоритм сжатия LZW</title>
		<link>http://www.studcode.ru/archiv/algoritm-szhatiya-lzw/</link>
		<comments>http://www.studcode.ru/archiv/algoritm-szhatiya-lzw/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:47:29 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=487</guid>
		<description><![CDATA[Данный метод сжатия данных был впервые обнародован в 1977г. Алгоритм на удивление прост. Если в двух словах, то LZW-сжатие заменяет строки символов некоторыми кодами. Это делается без какого-либо анализа входного текста. Вместо этого при добавлении каждой новой строки символов просматривается таблица строк. Сжатие происходит, когда код заменяет строку символов. Коды, генерируемые LZW-алгоритмом, могут быть любой [...]]]></description>
			<content:encoded><![CDATA[<p>Данный метод сжатия данных был впервые обнародован в 1977г. Алгоритм на удивление прост. Если в двух словах, то LZW-сжатие заменяет строки символов некоторыми кодами. Это делается без какого-либо анализа входного текста. Вместо этого при добавлении каждой новой строки символов просматривается таблица строк. Сжатие происходит, когда код заменяет строку символов. Коды, генерируемые LZW-алгоритмом, могут быть любой длины, но они должны содержать больше бит, чем единичный символ. Первые 256 кодов (когда используются 8-битные символы) по умолчанию соответствуют стандартному набору символов. Остальные коды соответствуют обрабатываемым алгоритмом строкам. Простая программа, приведенная ниже, работает с 12-битными кодами. Значения кодов 0 – 255 соответствуют отдельным байтам, а коды 256 &#8211; 4095 соответствуют подстрокам. Каждый раз, когда генерируется новый код, новая строка добавляется в таблицу строк. LZW постоянно проверяет, является ли строка уже известной, и, если так, выводит существующий код без генерации нового.</p>
<p><span id="more-487"></span></p>
<p><strong><em><span style="text-decoration: underline;">Процедура LZW-сжатия:</span></em></strong></p>
<p>СТРОКА = очередной символ из входного потока</p>
<p>WHILE входной поток не пуст DO</p>
<p>СИМВОЛ = очередной символ из входного потока</p>
<p>IF СТРОКА+СИМВОЛ в таблице строк THEN</p>
<p>СТРОКА = СТРОКА+СИМВОЛ</p>
<p>ELSE</p>
<p>вывести в выходной поток код для СТРОКА</p>
<p>добавить в таблицу строк СТРОКА+СИМВОЛ</p>
<p>СТРОКА = СИМВОЛ</p>
<p>END of IF</p>
<p>END of WHILE</p>
<p>вывести в выходной поток код для СТРОКА</p>
<p>Рассмотрим работу алгоритма на примере обработки входной строки /WED/WE/WEE/WEB/WET , которая является кратким списком английских слов, разделенных символом &#8220;/&#8221;. Как вы можете заметить, анализируя алгоритм, его работа начинается с того, что на первом шаге цикла он выполняет проверку на наличие строки &#8220;/W&#8221; в таблице. Когда он не находит эту строку, то генерирует код для &#8220;/&#8221; и добавляет в таблицу строку &#8220;/W&#8221;. Т.к. 256 символов уже определены для кодов 0 &#8211; 255, то первой определенной строке может быть поставлен в соответствие код 256. После этого система читает следующую букву (&#8221;E&#8221;), добавляет вторую подстроку (&#8221;WE&#8221;) в таблицу и выводит код для буквы &#8220;W&#8221;. Этот процесс повторяется до тех пор, пока вторая подстрока, состоящая из прочитанных символов &#8220;/&#8221; и &#8220;W&#8221;, не сопоставится со строковым номером 256. В этом случае система выводит код 256 и добавляет трехсимвольную подстроку в таблицу. Этот процесс продолжается до тех пор, пока не исчерпается входной поток и все коды не будут выведены.</p>
<p>Входная строка : /WED/WE/WEE/WEB/WET</p>
<p>Вход(символы)          Выход(коды)            Новые коды (таблица строк)</p>
<p>/W                                /                                 256 = /W</p>
<p>E                                 W                                257 = WE</p>
<p>D                                 E                                258 = ED</p>
<p>/                                  D                                259 = D/</p>
<p>WE                             256                             260 = /WE</p>
<p>/                                  E                                 261 = E/</p>
<p>WEE                           260                             262 = /WEE</p>
<p>/W                               261                             263 = E/W</p>
<p>EB                              257                             264 = WEB</p>
<p>/                                  B                                 265 = B/</p>
<p>WET                            260                            266 = /WET</p>
<p>&lt;EOF&gt;                       T</p>
<p>Как можно заметить, таблица строк быстро заполняется, т.к. новая строка добавляется в таблицу каждый раз, когда генерируется код. В этом явно вырожденном примере было выведено пять закодированных подстрок и семь символов. Если использовать 9-битные коды для вывода, то 19-символьная входная строка будет преобразована в 13.5-символьная выходную строку. Конечно, этот пример был выбран только для демонстрации. В действительности сжатие обычно не начинается до тех пор, пока не будет построена достаточно большая таблица, обычно после прочтения порядка 100 входных байт. Алгоритму сжатия соответствует свой алгоритм распаковки. Он получает выходной поток кодов от алгоритма сжатия и использует его для точного восстановления входного потока. Одной из причин эф- фективности LZW-алгоритма является то, что он не нуждается в хранении таблицы строк, полученной при сжатии. Таблица может быть точно восстановлена при распаковке на основе выходного потока алго- ритма сжатия. Это возможно потому, что алгоритм сжатия выводит СТРОКОВУЮ и СИМВОЛЬНУЮ компоненты кода прежде чем он поместит этот код в выходной поток. Это означает, что сжатые данные не обременены необходимостью тянуть за собой большую таблицу перевода. Алгоритм распаковки представлен ниже. В соответствии с алгоритмом сжатия, он добавляет новую строку в таблицу строк каждый раз, когда читает из входного потока новый код. Все, что ему необходимо сделать в добавок &#8211; это перевести каждый входной код в строку и переслать ее в выходной поток.</p>
<p><strong><em><span style="text-decoration: underline;">Процедура LZW-распаковки:</span></em></strong></p>
<p>читать СТАРЫЙ_КОД</p>
<p>вывести СТАРЫЙ_КОД</p>
<p>СИМВОЛ = СТАРЫЙ_КОД</p>
<p>WHILE входной поток не пуст DO</p>
<p>читать НОВЫЙ_КОД</p>
<p>IF NOT в таблице перевода НОВЫЙ_КОД THEN</p>
<p>СТРОКА = перевести СТАРЫЙ_КОД</p>
<p>СТРОКА = СТРОКА+СИМВОЛ</p>
<p>ELSE</p>
<p>СТРОКА = перевести НОВЫЙ_КОД</p>
<p>END of IF</p>
<p>вывести СТРОКУ</p>
<p>СИМВОЛ = первый символ СТРОКИ</p>
<p>добавить в таблицу перевода СТАРЫЙ_КОД+СИМВОЛ</p>
<p>СТАРЫЙ_КОД = НОВЫЙ_КОД</p>
<p>END of WHILE</p>
<p>Входные коды : / W E D 256 E 260 261 257 B 260 T</p>
<p>НОВЫЙ КОД           СТАРЫЙ КОД         СТРОКА        СИМВОЛ      Таблица</p>
<p>/                                   /                             /</p>
<p>W                                /                            W               W                    256 = /W</p>
<p>E                                 W                          E               E                     257 = WE</p>
<p>D                                E                           D               D                     258 = ED</p>
<p>256                             D                           /W              /                      259 = D/</p>
<p>E                                 256                         E              E                     260 = /WE</p>
<p>260                             E                          /WE           /                       261 = E/</p>
<p>261                             260                         E/                         E                     262 = /WEE</p>
<p>257                             261                       WE            W                    263 = E/W</p>
<p>B                                 257                          B                         B                     264 = WEB</p>
<p>260                             B                        /WE             /                       265 = B/</p>
<p>T                                 260                         T              T                     266 = /WET</p>
<p>Концепции, использованные в алгоритме сжатия, настолько просты, что весь алгоритм может быть записан в несколько строк. Но так как управление построением таблицы требует некоторых специальных действий, реализация несколько более сложна. В демонстрационной программе, приведенной ниже, использовались коды длиной 12, 13 и 14 бит. При длине кода 12 бит потенциально возможно хранить до 4096 строк в таблице. Каждый раз, когда читается новый символ, таблица строк должна просматриваться для сопоставления. Если сопоставление не найдено, новая строка должна быть добавлена в таблицу.</p>
<p>Здесь возникают две проблемы. Во-первых, таблица строк может достаточно быстро стать очень большой. Даже если длина строк в среднем ограничивается 3 или 4 символами каждая, верхний предел длин строк может легко превысить 7 или 8 байт на код. К тому же количество памяти, необходимой для хранения строк, заранее не известно, так как оно зависит от общей длины строк. Вторая проблема заключается в организации поиска строк. Каждый раз, когда читается новый символ, необходимо организовать поиск для новой строки вида СТРОКА+СИМВОЛ. Это означает поддержку отсортированного списка строк. В этом случае поиск для каждой строки включает число сравнений порядка log2 от общего числа строк.</p>
<p>Использование 12-битных слов потенциально позволяет выполнять не более 12 сравнений для каждого кода. Первая проблема может быть решена хранением строк как комбинаций код/символ. Так как каждая строка в действительности является представлением комбинации уже существующего кода и добавочного символа, можно хранить каждую строку как отдельный код плюс символ. Например в разобранном выше примере строка &#8220;/WEE&#8221; хранится как код 260 и символ &#8220;E&#8221;. Это позволяет использовать для хранения только 3 байта вместо 5 (включающих дополнительный байт для конца строки). Идя назад, можно определить, что код 260 хранится как код 256 плюс добавочный символ &#8220;E&#8221;. Наконец, код 256 хранится как &#8220;/&#8221; плюс &#8220;W&#8221;.</p>
<p>Выполнение сравнения строк является немного более трудным. Новый метод хранения увеличивает время, необходимое для сравнения строк, но он не влияет на число сравнений. Эта проблема решается использованием алгоритма хэширования для хранения строк. Это означает, что код 256 не хранится в каком-либо массиве по адресу 256, а хранится в массиве по адресу, сформированному на основе самой строки. При определении места хранения данной строки можно использовать тестовую строку для генерации хэшадреса и затем найти целевую строку однократным сравнением. Так как код для любой данной строки нельзя узнать в дальнейшем иначе как по его позиции в массиве, необходимо хранить код для данной строки совместно с данными строки.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/algoritm-szhatiya-lzw/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Арифметическое кодирование</title>
		<link>http://www.studcode.ru/archiv/arifmeticheskoe-kodirovanie/</link>
		<comments>http://www.studcode.ru/archiv/arifmeticheskoe-kodirovanie/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:45:16 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=482</guid>
		<description><![CDATA[Пpи аpифметическом кодиpовании текст пpедставляется вещественными числами в интеpвале от 0 до 1. По меpе кодиpования текста, отобpажающий его интеpвал уменьшается, а количество битов для его пpедставления возpастает. Очеpедные символы текста сокpащают величину интеpвала исходя из значений их веpоятностей, опpеделяемых моделью. Более веpоятные символы делают это в меньшей степени, чем менее веpоятные, и, следовательно, довабляют [...]]]></description>
			<content:encoded><![CDATA[<p>Пpи аpифметическом кодиpовании текст пpедставляется вещественными числами в интеpвале от 0 до 1. По меpе кодиpования текста, отобpажающий его интеpвал уменьшается, а количество битов для его пpедставления возpастает. Очеpедные символы текста сокpащают величину интеpвала исходя из значений их веpоятностей, опpеделяемых моделью. Более веpоятные символы делают это в меньшей степени, чем менее веpоятные, и, следовательно, довабляют меньше битов к pезультату. Пеpед началом pаботы соответствующий тексту интеpвал есть [0; 1). Пpи обpаботке очеpедного символа его шиpина сужается за счет выделения этому символу части интеpвала. Hапpимеp, пpименимк тексту “eaii!” алфавита a,e,i,o,u,! модель с постоянными веpоятностями.</p>
<p>Символ           Веpоятность              Интеpвал</p>
<p>a                          .2                         [0.0; 0.2)</p>
<p>e                          .3                         [0.2; 0.5)</p>
<p>i                           .1                         [0.5; 0.6)</p>
<p>o                           .2                         [0.6; 0.8)</p>
<p>u                           .1                         [0.8; 0.9)</p>
<p>!                           .1                         [0.9; 1.0)</p>
<p><span id="more-482"></span></p>
<p>И кодиpовщику, и декодиpовщику известно, что в самом начале интеpвал есть [0; 1). После пpосмо- тpа пеpвого символа “e”, кодиpовщик сужает интеpвал до [0.2; 0.5), котоpый модель выделяет этому символу. Втоpой символ “a” сузит этот новый интеpвал до пеpвой его пятой части, поскольку для “a”</p>
<p>выделен фиксиpованный интеpвал [0.0; 0.2). В pезультате получим pабочий интеpвал [0.2; 0.26), т.к. пpедыдущий интеpвал имел шиpину в 0.3 единицы и одна пятая от него есть 0.06. Следующему символу “i” соответствует фиксиpованный интеpвал [0.5; 0.6), что пpименительно к pабочему интеpвалу [0.2; 0.26) суживает его до интеpвала [0.23, 0.236). Пpодолжая в том же духе, имеем:</p>
<p>В начале                    [0.0; 1.0)</p>
<p>После пpосмотpа      &#8220;e&#8221; [0.2; 0.5 )</p>
<p>-&#8221;-&#8221;-&#8221;-                          &#8220;a&#8221; [0.2; 0.26 )</p>
<p>-&#8221;-&#8221;-&#8221;-                          &#8220;i&#8221; [0.23; 0.236 )</p>
<p>-&#8221;-&#8221;-&#8221;-                          &#8220;i&#8221; [0.233; 0.2336)</p>
<p>-&#8221;-&#8221;-&#8221;-                          &#8220;!&#8221; [0.23354; 0.2336)</p>
<p>Пpедположим, что все что декодиpовщик знает о тексте, это конечный интеpвал [0.23354; 0.2336). Он сpазу же понимает, что пеpвый закодиpованный символ есть “e”, т.к. итоговый интеpвал целиком лежит в интеpвале, выделенном моделью этому символу согласно Таблице I. Тепеpь повтоpим действия кодиpовщика:</p>
<p>Сначала                     [0.0; 1.0)</p>
<p>После пpосмотpа      &#8220;e&#8221; [0.2; 0.5)</p>
<p>Отсюда ясно, что втоpой символ &#8211; это “a”, поскольку это пpиведет к интеpвалу [0.2; 0.26), котоpый полностью вмещает итоговый интеpвал [0.23354; 0.2336). Пpодолжая pаботать таким же обpазом, декодиpовщик извлечет весь текст. Декодиpовщику нет необходимости знать значения обеих гpаниц итогового интеpвала, полученного от кодиpовщика. Даже единственного значения, лежащего внутpи него, напpимеp 0.23355, уже достаточ- но. (Дpугие числа &#8211; 0.23354,0.23357 или даже 0.23354321 &#8211; вполне годятся). Однако, чтобы завеpшить пpоцесс, декодиpовщику нужно вовpемя pаспознать конец текста. Кpоме того, одно и то же число 0.0 можно пpедставить и как “a”, и как “aa”, “aaa” и т.д. Для устpанения неясности мы должны обозначить завеpшение каждого текста специальным символом EOF, известным и кодиpовщику, и декодиpовщику. Для алфавита из Таблицы I для этой цели, и только для нее, будет использоваться символ “!”. Когда декодиpовщик встpечает этот символ, он пpекpащает свой пpоцесс.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/arifmeticheskoe-kodirovanie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Метод “стопка-книг“</title>
		<link>http://www.studcode.ru/archiv/metod-%e2%80%9cstopka-knig%e2%80%9c/</link>
		<comments>http://www.studcode.ru/archiv/metod-%e2%80%9cstopka-knig%e2%80%9c/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:41:01 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=474</guid>
		<description><![CDATA[Метод “стопка-книг“ не требует предварительного анализа входного файла и используется преимущественно в системах передачи данных. У кодировщика и декодировщика в памяти имеется кодовая таблица, в первой колонке которой перечислены символы в произвольном порядке, а во второй &#8211; коды, рассчитанные по методу Шеннона-Фано в порядке возрастания длины. При поступлению к кодировщику очередного символа от источника он [...]]]></description>
			<content:encoded><![CDATA[<p>Метод “стопка-книг“ не требует предварительного анализа входного файла и используется преимущественно в системах передачи данных. У кодировщика и декодировщика в памяти имеется кодовая таблица, в первой колонке которой перечислены символы в произвольном порядке, а во второй &#8211; коды, рассчитанные по методу Шеннона-Фано в порядке возрастания длины. При поступлению к кодировщику очередного символа от источника он просматривается в первой колонке таблицы и в канал передается его код. После этого символ перемещается в первую строку таблицы, где ему будет соответствовать самый короткий код. Декодировщик при получении кода, находит символ и также перемещает его в верхнюю строку таблицы. Таким образом, таблицы оказываются одинаковыми. В результате работы алгоритма часто используемые символы будут группироваться в верхней части таблицы, а редко используемые &#8211; “оседать“ в нижних строках. Для передачи текста в целом будет использоваться меньшее число кодовых символов, чем при равномерном кодировании. И чем выше избыточность, тем эффективнее будет алгоритм.</p>
<p><span id="more-474"></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/metod-%e2%80%9cstopka-knig%e2%80%9c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Метод Шеннона-Фано</title>
		<link>http://www.studcode.ru/archiv/metod-shennona-fano/</link>
		<comments>http://www.studcode.ru/archiv/metod-shennona-fano/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:39:48 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=469</guid>
		<description><![CDATA[Допyстим нам нyжно закодиpовать некотоpое сообщение: AABCDAABCА
Кодирование проводим в несколько этапов.
1. Строим таблицу встречаемости символов, делим каждое значение на общее число символов и располагаем символы в порядке уменьшения вероятностей:
A &#8211; 5               5/10 = 0.5
B &#8211; 2                2/10 = 0.2
C &#8211; 2                2/10 = 0.2
D – 1                1/10 = 0.1

2. После этого [...]]]></description>
			<content:encoded><![CDATA[<p>Допyстим нам нyжно закодиpовать некотоpое сообщение: AABCDAABCА</p>
<p>Кодирование проводим в несколько этапов.</p>
<p><strong>1</strong>. Строим таблицу встречаемости символов, делим каждое значение на общее число символов и располагаем символы в порядке уменьшения вероятностей:</p>
<p>A &#8211; 5               5/10 = 0.5</p>
<p>B &#8211; 2                2/10 = 0.2</p>
<p>C &#8211; 2                2/10 = 0.2</p>
<p>D – 1                1/10 = 0.1</p>
<p><span id="more-469"></span></p>
<p><strong>2</strong>. После этого стpоим кодовые комбинации пpостым методом. Делим столбик с веpоятностями таким обpазмо, чтобы сyмма веpоятностей веpхней части pавнялась пpиблизительно сyмме веpоятностей нижней части</p>
<p>0.5 &#8211; пеpвая часть = 0.5</p>
<p>&#8212;&#8211;</p>
<p>0.2 \</p>
<p>0.2 | &#8211; втоpая часть = 0.5</p>
<p>0.1 /</p>
<p><strong>3.</strong> Hапpитив веpоятностей веpхней части пpоставляем нyли, напpотив нижней &#8211; единицы. В нашем пpимеpе полyчим:</p>
<p>0.5        0</p>
<p>0.2        1</p>
<p>0.2        1</p>
<p>0.1        1</p>
<p><strong>4.</strong> Пpоделываем потом то же с pазделенными частями.В конце-концов пpидем к томy, что делить больше нечего.</p>
<p>А         0.5       0</p>
<p>B         0.2       10</p>
<p>C         0.2       110</p>
<p>D         0.1       111</p>
<p>В итоге сообщение, занимавшее 70 бит &#8211; AABCDAABC займет только 17 бит: 00101101110010110. Пpичем закодиpованное сообщение (это видно) не может быть pаскодиpовано несколькими способами, хотя длина кодов символов отличается. Чтобы пpочитать закодиpованное сообщение стpоится бинаpное деpево. В нашем слyчае оно бyдет такое:</p>
<p>()</p>
<p>/ \</p>
<p>0(A)    1</p>
<p>/ \</p>
<p>0(B)    1</p>
<p>/ \</p>
<p>0(C)  1(D)</p>
<p><strong><em>Недостатки</em></strong> метода Шеннона-Фано:</p>
<p>1. Низкая скорость, поскольку требуется предварительная обработка файла.</p>
<p>2. Эффективность кодирования не всегда гарантирована.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/metod-shennona-fano/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Равномерное и неравномерное кодирование</title>
		<link>http://www.studcode.ru/archiv/ravnomernoe-i-neravnome/</link>
		<comments>http://www.studcode.ru/archiv/ravnomernoe-i-neravnome/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:38:36 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=465</guid>
		<description><![CDATA[Кодирование &#8211; это сопоставление сообщения одного источника с некоторым алфавитом сообщению другого источника с другим алфавитом. Если закодированное сообщение будет занимать меньше места на машинном носителе при возможности восстановления исходного сообщения, то в этом случае при кодировании достигается сжатие информации. Равномерное кодирование заключается в сопоставлению символам кодов одинаковой длины. В этом случае говорить об эффективности [...]]]></description>
			<content:encoded><![CDATA[<p><strong><em>Кодирование</em></strong> &#8211; это сопоставление сообщения одного источника с некоторым алфавитом сообщению другого источника с другим алфавитом. Если закодированное сообщение будет занимать меньше места на машинном носителе при возможности восстановления исходного сообщения, то в этом случае при кодировании достигается сжатие информации. Равномерное кодирование заключается в сопоставлению символам кодов одинаковой длины. В этом случае говорить об эффективности можно только в том случае, когда вероятности появления символов источника равны, то есть его энтропия максимальна.</p>
<p><span id="more-465"></span></p>
<p>В качестве примера равномерного кода можно назвать ASCII-таблицу, где каждому из 256 символов сопоставлено двоичное значение от 00000000 до 11111111. Независимо от вероятности появления символа на его представление отводится 1 байт, или 8 бит. Как известно, национальные языки обладают большой избыточностью, то есть разницей между энтропией источника и максимально возможной энтропией, обусловленной равной вероятностью появления любого символа из алфавита. Например, избыточность русского языка составляет 70%, а английского &#8211; 50%. Это в частности означает, что некоторые буквы появляются в тексте гораздо чаще других и поэтому использовать равномерное кодирование нерационально.</p>
<p>При неравномерном кодировании часто встречающимся символам сопоставляются более короткие кодовые последовательности, редко встречающимся &#8211; более длинные. За счет этого удается значительно сократить объем файла без потерь информации. Существует несколько методов неравномерного кодирования, важнейших из которых является метод Шеннона-Фано.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/ravnomernoe-i-neravnome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Алгоритмы кодирования и сжатия данных</title>
		<link>http://www.studcode.ru/archiv/algoritmy-kodirovaniya/</link>
		<comments>http://www.studcode.ru/archiv/algoritmy-kodirovaniya/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:37:29 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=462</guid>
		<description><![CDATA[Введение
Алгоритмы кодирования и сжатия данных нашли широкое применение в связи, цифровой обработке сигналов, в программых сжатия и архивации, мультимедийных системах. Для того чтобы разработать и исследовать эти алгоритмы необходимо рассмотреть базовые понятия науки, называемой теорией информации.
Проблема измерения количества информации
Измерение информации в быту (информация как новизна). Вы получили какое-то сообщение (например, прочитали статью в любимом журнале). [...]]]></description>
			<content:encoded><![CDATA[<h2>Введение</h2>
<p>Алгоритмы кодирования и сжатия данных нашли широкое применение в связи, цифровой обработке сигналов, в программых сжатия и архивации, мультимедийных системах. Для того чтобы разработать и исследовать эти алгоритмы необходимо рассмотреть базовые понятия науки, называемой теорией информации.</p>
<h2>Проблема измерения количества информации</h2>
<p><strong>Измерение информации в быту (информация как новизна).</strong> Вы получили какое-то сообщение (например, прочитали статью в любимом журнале). В этом сообщении содержится какое-то количество информации. Как оценить, сколько информации вы получили? Другими словами, как измерить информацию? Можно ли сказать, что чем больше статья, тем больше информации она содержит? Разные люди, получившие одно и то же сообщение, по-разному оценивают количество информации, содержащееся в нем. Это происходит оттого, что знания людей об этих событиях, явлениях до получения сообщения были различными. Поэтому те, кто знал об этом мало, сочтут, что получили много информации, те же, кто знал больше, чем написано в статье, скажут, что информации не получили вовсе. Таким образом, количество информации в сообщении зависит от того, насколько ново это сообщение для получателя. При таком подходе непонятно, по каким критериям можно ввести единицу измерения информации. Следовательно, с точки зрения информации как новизны мы не можем оценить количество информации, содержащейся в научном открытии, новом музыкальном стиле, новой теории общественного развития.</p>
<p><span id="more-462"></span></p>
<p><strong>Измерение информации в технике. </strong>В технике часто используют простой и грубый способ определения количества информации, который может быть назван объемным. Он основан на подсчете числа символов в сообщении, т.е. связан с его длиной и не учитывает содержания. Длина сообщения зависит от числа различных символов, употребляемых для записи сообщения. Например, слово “мир“ в русском алфавите записывается тремя знаками, в английском &#8211; пятью (реасе), а в КОИ-8 &#8211; двадцатью четырьмя битами (111011011110100111110010). В вычислительной технике применяются две стандартные единицы измерения: бит (binary digit) и байт (byte). Конечно, будет правильно, если вы скажете: &#8220;В слове &#8220;Рим&#8221; содержится 24 бита информации, а в сообщении &#8220;миру мир!&#8221; &#8211; 72 бита&#8221;. Однако, прежде чем измерить информацию в битах, вы определяете количество символов в этом сообщении. <strong></strong></p>
<p>Нам привычнее работать с символами, машине – с кодами. <em>Каждый символ не случайно кодируется 8-битным кодом.</em> Мы уже обсуждали, почему это так. Поэтому для удобства была введена более &#8220;крупная&#8221; единица информации в технике (преимущественно в вычислительной) &#8211; байт. Теперь вам легче подсчитать количество информации в техническом сообщении – оно совпадает с количеством символов в нем.</p>
<p><strong>Измерение информации в теории информации (информация как снятая неопределенность).</strong> Пусть имеется колода из 32 игральных карт (от семерок до тузов). Задумывается одна из карт. Необходимо, задавая вопросы, на которые будут даны ответы &#8220;да&#8221; или &#8220;нет&#8221;, угадать задуманную карту. Первый вопрос: &#8220;Задумана карта черной масти?&#8221; Ответ: &#8220;Нет&#8221;. Ответ уменьшает неопределенность вдвое и приносит отгадывающему 1 бит информации. Второй вопрос: &#8220;Задумана карта бубновой масти?&#8221; Ответ: &#8220;Да&#8221;. Это еще один бит информации, исходная неопределенность уменьшилась в 4 раза. Третий вопрос: &#8220;Задумана карта &#8211; картинка?&#8221; Ответ: &#8220;Нет&#8221;. Третий бит информации, первоначальная неопределенность уменьшилась в 8 раз. Четвертый вопрос: &#8220;Задуманная карта младше девятки?&#8221; Ответ: &#8220;Да&#8221;. Еще один бит информации, первоначальная неопределенность уменьшилась в 16 раз. Пятый вопрос: &#8220;Задумана восьмерка бубновая?&#8221; Ответ: &#8220;Нет&#8221;. Отгадывающий получил пятый бит информации, исходная неопределенность уменьшилась в 32 раза. Последний ответ позволяет с уверенностью сказать, что была задумана бубновая семерка. Неопределенности не осталось. Очень приближенно можно считать, что количество информации в сообщении о каком-то событии совпадает с количеством вопросов, которые необходимо задать. Чтобы получить ту же информацию, ответ на эти вопросы может быть лишь &#8220;да&#8221; или &#8220;нет&#8221;. Причем событие, о котором идет речь, должно иметь равновероятные исходы (монета может упасть только &#8220;орлом&#8221; или &#8220;решкой&#8221; &#8211; два равновероятных исхода, задуманной может оказаться любая из 32 карт &#8211; 32 равновероятных исхода и т. п.).</p>
<p>Таким образом, количество информации зависит от вероятности получения сообщения. В теории информации количеством информации называют числовую характеристику сигнала, не зависящую от его формы и содержания и характеризующую неопределенность, которая исчезает после получения сообщения в виде данного сигнала. В этом случае количество информации зависит от вероятности получения сообщения о том или ином событии.</p>
<p>В 100 Мб можно уместить:</p>
<p>Страниц текста &#8211; 50 000 или 150 романов</p>
<p>Цветных слайдов высочайшего качества &#8211; 150</p>
<p>Аудиозапись речи видного политического деятеля &#8211; 1.5 часа</p>
<p>Музыкальный фрагмент качества СD-стерео &#8211; 10 минут</p>
<p>Фильм высокого качества записи &#8211; 15 секунд</p>
<p>Протоколы операций с банковским счетом &#8211; за 1000 лет</p>
<p>Для цифровой характеристики источника сообщения используется математическое ожидание количества информации в отдельных сообщениях называемых<strong><em><span style="text-decoration: underline;"> энтропией.</span></em></strong></p>
<p>H(U) = M {-logP(u<sub>i</sub>)} = М{}=</p>
<p>Энтропия характеризует среднее количество информации, которое может быть получено от источника.</p>
<p>Чем больше энтропия источника, тем больше степень неожиданности выдаваемых им сообщений в среднем, т.е. тем более неопределенным является ожидание сообщений. Если вероятности появления каждого из возможных сообщений одинаковы, то в этом случае энтропия источника максимальна, а сжимать эти сообщения практически бесполезно. Но если одни сообщения (символы) появляются чаще других, то результат работы источника может быть с успехом подвергнут сжатию.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/algoritmy-kodirovaniya/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Алгоритмы, основанные на простых множествах</title>
		<link>http://www.studcode.ru/archiv/algoritmy-osnovannye/</link>
		<comments>http://www.studcode.ru/archiv/algoritmy-osnovannye/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:34:43 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=457</guid>
		<description><![CDATA[Представление множеств
Множества &#8211; одно из основных понятий вычислительной математики и программирования. Почти каждая математическая модель, описывающая объекты реального мира содержит множества. Под простыми множествами мы будем понимать последовательность простых данных, то есть символов и чисел.
Основными структурами данных для хранения простых множеств являются массивы. Массивы могут быть одномерными и многомерными (наиболее распространены двумерные, или матрицы). Последовательность [...]]]></description>
			<content:encoded><![CDATA[<p><strong><span style="text-decoration: underline;">Представление множеств</span></strong></p>
<p><em>Множества</em> &#8211; одно из основных понятий вычислительной математики и программирования. Почти каждая математическая модель, описывающая объекты реального мира содержит множества. Под простыми множествами мы будем понимать последовательность простых данных, то есть символов и чисел.</p>
<p>Основными структурами данных для хранения простых множеств являются массивы. Массивы могут быть одномерными и многомерными (наиболее распространены двумерные, или матрицы). Последовательность элементов одномерного массива имеет вид: A={1,2,3,4}. Произвольную последовательность элементов массива можно записать как (1, 2, 3). Для операций над элементами множеств могут привлекаться вспомогательные переменные. Часто используются указатели массива: l – левая граница, r &#8211; правая граница. В процессе работы алгоритма значение l увеличивается, а r &#8211; уменьшается.</p>
<p><span id="more-457"></span></p>
<p><strong><span style="text-decoration: underline;">Обмен значений двух переменных</span></strong></p>
<p>Эта задача является наиболее распространенной и используется во многих, более сложных алгоритмов. Наиболее общее ее решение гласит &#8211; необходима третья переменная.</p>
<p><strong>Алгоритм 1. Обмен значений двух переменных</strong></p>
<p>SWAP(A,B)</p>
<p>t ←A</p>
<p>A←B</p>
<p>B←t</p>
<p>Однако, для числовых A и В можно использовать алгоритм без дополнительной переменной.</p>
<p><strong>Алгоритм 2. Обмен значений двух переменных-2</strong></p>
<p>SWAP(A,B)</p>
<p>А← A + B</p>
<p>B ←A &#8211; B</p>
<p>A←A &#8211; B</p>
<p>Если начальные значения А и В обозначим А0, В0, то в каждой строке алгоритма А и В принимают следующие значения:</p>
<p>А = А0 + В0,             В = В0</p>
<p>А = А0 + В0,             В = А0</p>
<p>А = В0,           В = А0</p>
<p><strong><span style="text-decoration: underline;">Нахождение минимального и максимального элемента</span></strong></p>
<p>Одной из наиболее часто встречающихся задач является поиск элемента массива, удовлетворяющего заданным требованиям. В этом случае производят однократный перебор всех элементов и проверку каждого значения при заданном условии. Поиск макс./мин. значений может быть также осуществлен при однократном проходе цикла:</p>
<p><strong>Алгоритм 3. Нахождение мин/макс значений элементов</strong></p>
<p>A[] ← (A<sub>1</sub>,A<sub>2</sub>, &#8230;A<sub>N</sub>)</p>
<p>MINMAX(A[])</p>
<p>Min←A[1]</p>
<p>max ←A[1]</p>
<p>for I←2 to N do</p>
<p>if A[I] &lt; min then min←A[I] fi</p>
<p>if A[I] &gt; max then max←A[I] fi</p>
<p>od</p>
<p><strong>Группировка элементов массива</strong></p>
<p>Дан массив А и число В. Переставить элементы в массиве А таким образом, чтобы слева от некоторой границы стояли числа меньше В, а справа &#8211; больше В.</p>
<p><strong>Алгоритм 4. Группировка элементов массива</strong></p>
<p>A[] ← (A<sub>1</sub>,A<sub>2</sub>, &#8230;A<sub>N</sub>)</p>
<p>GROUPING1(A[],N,B)</p>
<p>l ←0</p>
<p>r ←N</p>
<p>while l ≠ r do</p>
<p>if A[l + 1]≤B then l←l + 1</p>
<p>elsif A[r] ≥ B then r←r + 1</p>
<p>else SWAP(A[l + 1],A[r])</p>
<p>l ←l + 1, r←r &#8211; 1</p>
<p>fi</p>
<p>od</p>
<p>Та же задача, но требуется, чтобы сначала шли элементы, меньшие B, затем равные B, а лишь затем большие B.</p>
<p><span style="text-decoration: underline;">Решение.</span> Теперь потребуются три границы: до первой будут идти элементы, меньшие B, от первой до второй &#8211; равные B, затем неизвестно какие до третьей, а после третьей &#8211; большие B. (Более симметричное решение использовало бы четыре границы, но вряд ли игра стоит свеч.) В качестве очередного рассматриваемого элемента берем элемент справа от средней границы.</p>
<p><strong>Алгоритм 5. Группировка элементов массива-2</strong></p>
<p>A[]← (A<sub>1</sub>,A<sub>2</sub>, &#8230;A<sub>N</sub>)</p>
<p>GROUPING2(A[],N,B)</p>
<p>l← 0</p>
<p>m← 0</p>
<p>r← N</p>
<p>while m ≠ r do</p>
<p>if A[m + 1] = B then</p>
<p>m ← m + 1</p>
<p>elsif A[m + 1] &gt; B then</p>
<p>SWAP(A[m + 1],A[r])</p>
<p>r← r &#8211; 1</p>
<p>else</p>
<p>SWAP(A[m + 1],A[l + 1])</p>
<p>l ← l + 1,m←m + 1</p>
<p>fi</p>
<p>od</p>
<p><strong><span style="text-decoration: underline;">Генерирование перестановок</span></strong></p>
<p>Рассматривая задачу комивояжера мы столкнулись с необходимостью генерировать перестановки в массиве целых чисел, означающих номера городов. Под перестановкой мы будем понимать возможную последовательность элементов массива. Например, для массива из трех элементов A={1,2,3} можно указать 6 различных последовательностей: (1, 2, 3), (2, 1, 3), (2, 3, 1), (3, 2, 1), (3, 1, 2), (1, 3, 2). Число перестановок для множества из N элементов равно (N!). А вот пример программы, которая генерирует перестановки, используя антилексографический порядок (описать алгоритм самостоятельно) для перебора всех маршрутов в задаче комивояжера:</p>
<pre><code>
#include &lt;stdio.h&gt;
#include &lt;conio.h&gt;
int N=4;
void reverse(int *tours,int N)
{
int i=1,j=N,t;
while(i&lt;j)
{
t=tours[i];
tours[i]=tours[j];
tours[j]=t;
i++;j--;
}
}
void antilex(int *tours,int m)
{
int t;
if(m==1)
{
for(int k=1;k&lt;=N;k++)
printf("%d ",tours[k]);
printf("\n");
}
else
for(int i=1;i&lt;=m;i++)
{
antilex(tours,m-1);
if(i&lt;m)
{
t=tours[i];
tours[i]=tours[m];
tours[m]=t;
reverse(tours,m-1);
}
}
}
void main(void)
{
int tours[4];
for(int i=1;i&lt;=N;i++)
tours[i]=i;
clrscr();
antilex(tours,N);
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/algoritmy-osnovannye/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Сложность проблем</title>
		<link>http://www.studcode.ru/archiv/slozhnost-problem/</link>
		<comments>http://www.studcode.ru/archiv/slozhnost-problem/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:28:37 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=452</guid>
		<description><![CDATA[Существует теория сложности, которая классифицирует не только сложность самих алгоритмов, но и сложность самих задач. Теория рассматривает минимальное время и объем памяти, необходимые для решения самого трудного варианта проблемы на теоритическом компьютере, или машине Тьюринга.
Проблемы, которые можно решить с помощью алгоритмов с полиномиальным временем, называют решаемыми, потому что при разумных входных данных обычно могут быть [...]]]></description>
			<content:encoded><![CDATA[<p>Существует теория сложности, которая классифицирует не только сложность самих алгоритмов, но и сложность самих задач. Теория рассматривает минимальное время и объем памяти, необходимые для решения самого трудного варианта проблемы на теоритическом компьютере, или машине Тьюринга.</p>
<p>Проблемы, которые можно решить с помощью алгоритмов с полиномиальным временем, называют <em>решаемыми</em>, потому что при разумных входных данных обычно могут быть решены за разумное время (точное определение ” разумности” зависит от конкретных обстоятельств).</p>
<p>Проблемы, которые невозможно решить за полиномиальное время, называют <em>нерешаемыми</em>, потому что нахождение их решений быстро становится невозможным. Нерешаемые проблемы иногда называют трудными.</p>
<p><span id="more-452"></span></p>
<p>Алан Тьюринг доказал, что некоторые проблемы принципиально неразрешимы, то есть даже отвлекаясь от временной сложности, невозможно создать алгоритм их решения.</p>
<p>Вот некоторые из трудных задач:</p>
<p>• Задача комивояжера. Комивояжер должен объехать N городов с целью осуществления продажи своих товаров. Все N городов соединены дорогами по принципу &#8220;каждый с каждым&#8221;. Известна стоимость проезда между двумя любыми городами. Найти оптимальный маршур движения так, чтобы побывать во всех городах и при этом иметь минимальные затраты на дорогу.</p>
<p>• Проблема тройного брака. В комнате n мужчин, n женщин и n чиновников. Есть список разрешенных браков, записи которого состоят из одного мужчины, одной женщины и одного регистрирующего чиновника. Если дан этот список троек, то возможно ли построить n браков так, чтобы любой либо сочетался браком только с одним человеком или регистрировал только один брак?</p>
<p>• Тройная выполнимость. Есть список n логических выражений, каждое с тремя переменными.</p>
<p>Например: если (x и y) то z, (x и y) или не z и т.д. Существуют ли такие значения всех переменных, чтобы все утверждения были истинными?</p>
<p><span style="text-decoration: underline;">Пример 1.</span> Рассмотрим проблему вскрытия алгоритма шифрования по ключу. Временная сложность такого вскрытия пропорциональна числу возможных ключей, которое экспоненциально зависит от длины ключа. Если n &#8211; длина ключа, то сложность вскрытия грубой силой равна O(2n). При n бит сложность равна 256 и в этом случае вскрытие возможно за приемлимое время. При n = 112 бит сложность равна 2112 вскрытие становится невозможным.</p>
<p><span style="text-decoration: underline;">Пример 2.</span> Рассмотрим в качестве примера задачу комивояжера. Комивояжер должен объехать N городов с целью осуществления продажи своих товаров. Все N городов соединены дорогами по принципу &#8220;каждый с каждым&#8221;. Известна стоимость проезда между двумя любыми городами. Найти оптимальный маршур движения так, чтобы побывать во всех городах и при этом иметь минимальные затраты на дорогу. Исходная информация задана в виде перечня городов и соответствующей матрицы стоимостей, то есть двумерного массива с элементами C<sub>ij</sub> , равными стоимости проезда из города i в город j. В данном случае матрица имеет N строк и N столбцов. Следует также уточнить, что маршрут начинается и заканчивается в одном (базовом) городе и не может дважды проходить через один и тот же город.</p>
<p><span style="text-decoration: underline;">Решение</span> (метод грубого перебора).</p>
<p>Произвольно пронумеруем N городов целыми числами от 1 до N, причем базовый город имеет номер N. Каждый тур (один из возможных маршрутов) однозначно соответствует перестановке целых чисел 1, 2, ..N &#8211; 1. Для каждой перестановки строим тур и определяем его стоимость. Обрабатывая все перестановки запоминаем маршрут, который имеет на текущий момент самую низкую стоимость. Если находится маршрут с меньшей стоимостью, то все дальнейшие сравнения осуществляем с ним.</p>
<p><em><span style="text-decoration: underline;">Алгоритм 1. Задача комивояжера</span></em></p>
<p>TOUR ←1</p>
<p>MIN ← 1</p>
<p>for I ←1 to (N &#8211; 1)! do</p>
<p>P ← get P          (получение I-ой перестановки целых чисел 1,2,..N-1)</p>
<p>T(p),COST(T(p))    Строим тур T(P) and Вычисляем стоимость COST(T(P))</p>
<p>if COST(T(P)) &lt; MIN then</p>
<p>TOUR←T(p),</p>
<p>MIN←COST(T(P))</p>
<p>fi</p>
<p>od</p>
<p>Попробуем оценить сложность данного алгоритма. Алгоритм является факториальным, с оценкой O(n!). В задаче требуется найти (N &#8211; 1)! перестановок целых чисел. Если даже требуется только один шаг для каждой перестановки, то эта часть алгоритма потребует O[(n - 1)!] шагов, поэтому любая верхняя граница для общего времени работы должна быть O(n!). Построим таблицу, иллюстрирующую вычислительную сложность алгоритма, предполагая, что производительность компьютера 1GFLOPS (1000000000 op/s).</p>
<p><span style="text-decoration: underline;">Кол-во городов, N               Кол-во туров                        T,с                   T,дн                T,лет</span></p>
<p>2                                             2                      2e-08                &lt;&lt; 1                &lt;&lt; 1</p>
<p>3                                             6                      6e-08                &lt;&lt; 1               &lt;&lt;1</p>
<p>4                                             24                    2e-07                &lt;&lt; 1               &lt;&lt; 1</p>
<p>10                                           4e+06              4e-02                &lt;&lt; 1               &lt;&lt; 1</p>
<p>15                                           13e+12            1e+04               0.15                &lt;&lt; 1</p>
<p>18                                           6e+15              6e+07               740                 20</p>
<p>19                                           1e+17              1e+09              14000              390</p>
<p>20                                           2e+18              2e+10              280000            770</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/slozhnost-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Классификация по сложности</title>
		<link>http://www.studcode.ru/archiv/klassifikaciya-po-slozhnosti/</link>
		<comments>http://www.studcode.ru/archiv/klassifikaciya-po-slozhnosti/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 19:25:11 +0000</pubDate>
		<dc:creator>sleepes</dc:creator>
				<category><![CDATA[Теория алгоритмов]]></category>
		<category><![CDATA[лекции]]></category>

		<guid isPermaLink="false">http://www.studcode.ru/?p=447</guid>
		<description><![CDATA[Обычно алгоритмы классифицируют в соответствии с их временной сложностью. Можно выделить следующие их типы:
1. Постоянный &#8211; сложность оценивается как O(1).
2. Линейный &#8211; оценка равна O(n).
3. Квадратный &#8211; O(n2)
4. Кубический, полиноминальный &#8211; O(n3),O(nm).
5. Экспоненциальный &#8211; O(tp(n)), t- константа, p(n) &#8211; некоторая полиномиальная функция.
6. Факториальный - O(n!). Обладает наибольшей временной сложностью среди всех известных типов.

С ростом n [...]]]></description>
			<content:encoded><![CDATA[<p>Обычно алгоритмы классифицируют в соответствии с их временной сложностью. Можно выделить следующие их типы:</p>
<p>1. <em>Постоянный</em> &#8211; сложность оценивается как O(1).</p>
<p>2. <em>Линейный</em> &#8211; оценка равна O(n).</p>
<p>3. <em>Квадратный</em> &#8211; O(n<sup>2</sup>)</p>
<p>4. <em>Кубический, полиноминальный</em> &#8211; O(n<sup>3</sup>),O(n<sup>m</sup>).</p>
<p>5. <em>Экспоненциальный</em> &#8211; O(t<sup>p(n)</sup>), t- константа, p(n) &#8211; некоторая полиномиальная функция.</p>
<p>6. <em>Факториальный </em>- O(n!). Обладает наибольшей временной сложностью среди всех известных типов.</p>
<p><span id="more-447"></span></p>
<p>С ростом n временная сложность может стать настолько огромной, что это повлияет на практическую реализуемость алгоритма. Рассмотрим таблицу, в которой сравнивается время выполнения алгоритмов разных типов при n = 10<sup>6</sup>, при условии, что единицей времени для компьютера является микросекунда.</p>
<p><span style="text-decoration: underline;">Тип                 Сложность                Кол-во операций      Время при 106 операций в сек.</span></p>
<p>Постоянные              O(1)                            1                                 1мкс</p>
<p>Линейные                 O(n)                            10<sup>6</sup> 1 с</p>
<p>Квадратичные          O(n<sup>2</sup>)                           10<sup>12</sup> 11.6 дн.</p>
<p>Кубические               O(n<sup>3</sup>)                           10<sup>18</sup> 32000 лет</p>
<p>Экспоненциальные  O(2<sup>n</sup>)                          10<sup>301030 </sup> в 10<sup>301006</sup> раз больше времени существования Вселенной</p>
]]></content:encoded>
			<wfw:commentRss>http://www.studcode.ru/archiv/klassifikaciya-po-slozhnosti/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

