Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<stdio.h>
- // Функция подсчитывает количество каждого из 256 символов в исходном
- // массиве wrkdata длиной size и сохраняет это количество в массив stat
- void GetCharsOccurrence(unsigned long size,unsigned char*wrkdata,unsigned long*stat)
- {
- unsigned long n;
- // Инициализация статистики нулями
- for(n=0;n<256;n++)
- {
- stat[n]=0;
- };
- // Подсчёт количества
- for(n=0;n<size;n++)
- {
- stat[wrkdata[n]]+=1;
- };
- };
- // Элемент бинарного дерева
- struct TreeNode
- {
- unsigned long Weight;
- unsigned char Sign;
- TreeNode*Left;
- TreeNode*Rght;
- };
- // Элемент кольцевого списка
- struct CListNode
- {
- TreeNode*TNode;
- CListNode*Prev;
- CListNode*Next;
- };
- // Упакованная битовая последовательность
- struct PackedData
- {
- unsigned long BuffSize;
- unsigned char*Buff;
- unsigned long ByteCount;
- unsigned char BitCount;
- unsigned long ByteCount2;
- unsigned char BitCount2;
- };
- // Элемент таблицы
- struct CodeTableCell
- {
- unsigned char Length;
- unsigned long Bits;
- unsigned long Weight;
- };
- // Добавление элемента к кольцевому списку
- void AddCListNode(CListNode**root,TreeNode*node)
- {
- CListNode*tmp;
- if(*root)
- // Если кольцевой список имеет элементы
- {
- // Сохраняем указатель на последний элемент списка
- tmp=(*root)->Prev;
- // Элемент перед первым в списке -- новый элемент
- (*root)->Prev=new CListNode;
- // Элемент перед новым -- бывший последний
- (*root)->Prev->Prev=tmp;
- // Элемент после добавленного -- первый элемент списка
- (*root)->Prev->Next=*root;
- // Элемент после бывшего последнего -- добавленный
- tmp->Next=(*root)->Prev;
- }
- else
- // Если кольцевой список пуст
- {
- // Первый элемент списка -- новый элемент
- *root=new CListNode;
- // Следующий и предыдуший элементы списка в кольце из одного
- // элемента -- это собственно сам этот элемент
- (*root)->Prev=*root;
- (*root)->Next=*root;
- };
- // Добавленный элемент указывает на элемент бинарного дерева
- (*root)->Prev->TNode=node;
- };
- // Проверка единственности элемента
- int isCListNodeAlone(CListNode*root)
- {
- if(root)
- // Если в списке есть элементы
- {
- // Проверяем единственность и возвращаем результат
- return root->Next==root;
- }
- else
- {
- return-1;
- };
- };
- // Удаление элемента из кольцевого списка
- void RemoveCListNode(CListNode**root,CListNode**node)
- {
- if(*node)
- // Если в списке есть элементы
- {
- if(isCListNodeAlone(*node))
- // Если в кольцевом списке всего один элемент
- {
- // Обнуление указателей удаляемого элемента
- (*node)->Prev=0;
- (*node)->Next=0;
- // Удаление элемента
- delete*node;
- // Обнуление указателя на элемент
- *node=0;
- *root=0;
- }
- else
- // Если в кольцевом списке более одного элемента
- {
- if(*node==*root)
- // Если удаляемый элемент -- корневой элемент списка
- {
- // Новый корень списка -- второй элемент списка
- *root=(*root)->Next;
- }
- // Следующий элемент списка теперь должен ссылаться на предыдущий
- (*node)->Next->Prev=(*node)->Prev;
- // Предыдущий элемент списка теперь должен ссылаться на следующий
- (*node)->Prev->Next=(*node)->Next;
- // Обнуление указателей удаляемого элемента
- (*node)->Prev=0;
- (*node)->Next=0;
- // Удаление элемента
- delete*node;
- // Обнуление указателя на элемент
- *node=0;
- };
- };
- };
- // Функция производит поиск и возвращает два узла кольцевого списка, которые
- // ссылаются на листья/ветви бинарного дерева, имеющие наименьший вес
- void GetTwoLeastWeightedNodes(CListNode*root,CListNode**node1,CListNode**node2)
- {
- // Инициализация выходных переменных
- *node1=0;
- *node2=0;
- if(root)
- // Если в кольцевом списке имеются элементы
- {
- // Указатель на элемент кольцевого списка, обрабатываемый в данных момент
- CListNode*currnode;
- // Первое приближение для первого легчайшего элемента -- первый элемент списка
- *node1=root;
- // Текущий рабочий элемент -- второй элемент списка
- currnode=root->Next;
- // Цикл поиска первого легчайшего элемента
- while(currnode!=root)
- // Выполнять до тех пор, пока текущим элементом не станет первый элемент списка
- {
- if((*node1)->TNode->Weight>currnode->TNode->Weight)
- // Если вес легчайшейшего элемента больше веса текущего рабочего
- {
- // Легчайшим элементом будет текущий рабочий
- *node1=currnode;
- };
- // Следующий проверяемый элемент
- currnode=currnode->Next;
- };
- if(*node1==root)
- // Если первый легчайший элемент -- первый элемент списка
- {
- // Первым приближением для второго легчайшего элемента будет второй элемент списка
- *node2=root->Next;
- // А текущим рабочим элементом -- третий элемент списка
- currnode=(*node2)->Next;
- }
- else
- // Если первый легчайший элемент не является первым элементом списка
- {
- // Первым приближением для второго легчайшего элемента будет первый элемент списка
- *node2=root;
- // А текущим рабочим элементом -- второй элемент списка
- currnode=(*node2)->Next;
- };
- // Цикл поиска второго легчайшего элемента
- while(currnode!=root)
- // Выполнять до тех пор, пока текущим элементом не станет первый элемент списка
- {
- if((*node2)->TNode->Weight>currnode->TNode->Weight&&currnode!=*node1)
- // Если вес второго легчайшего элемента больше веса текущего рабочего
- // и текущий рабочий не является первым легчайшим
- {
- // Вторым легчайшим элементом будет текущий рабочий
- *node2=currnode;
- };
- // Следующий проверяемый элемент
- currnode=currnode->Next;
- };
- };
- };
- // Максимальная глубина дерева
- unsigned char GetMaxTreeDepth(TreeNode*root)
- {
- if(root)
- // Если список не пуст
- {
- if(root->Left==0)
- // Если текущий элемент лист
- {
- // Вернуть значение
- return 1;
- }
- else
- // Если текущий элемент -- ветвь
- {
- // Промежуточные значения
- unsigned char tmp1,tmp2;
- // Определить максимальную глубину каждой ветви
- tmp1=GetMaxTreeDepth(root->Left);
- tmp2=GetMaxTreeDepth(root->Rght);
- // Вернуть еденицу плюс максимальное значение
- return((tmp1>tmp2)?tmp1:tmp2)+1;
- };
- }
- else
- // Если список же пуст
- {
- return 0;
- };
- };
- // Минимальная глубина дерева
- unsigned char GetMinTreeDepth(TreeNode*root)
- {
- if(root)
- // Если список не пуст
- {
- if(root->Left==0)
- // Если текущий элемент лист
- {
- // Вернуть значение
- return 1;
- }
- else
- // Если текущий элемент -- ветвь
- {
- // Промежуточные значения
- unsigned char tmp1,tmp2;
- // Определить минимальную глубину каждой ветви
- tmp1=GetMinTreeDepth(root->Left);
- tmp2=GetMinTreeDepth(root->Rght);
- // Вернуть еденицу плюс минимальное значение
- return((tmp1<tmp2)?tmp1:tmp2)+1;
- };
- }
- else
- // Если список же пуст
- {
- return 0;
- };
- };
- // Процедура построения дерева Хаффмана
- void MakeHuffmanTree(unsigned long*stat,TreeNode**root)
- {
- unsigned long n;
- // Указатель на вспомогательный кольцевой список
- CListNode*rootlist=0;
- // Временный указатель на элемент бинарного дерева
- TreeNode*tmpnode;
- // Добавление элементов в кольцевой список
- for(n=0;n<256;n++)
- {
- if(stat[n])
- // Если символы с текущим кодом вообще встречаются в последовательности
- {
- // Создание и инициализация листа бинарного дерева Хаффмана
- tmpnode=new TreeNode;
- tmpnode->Left=0;
- tmpnode->Rght=0;
- tmpnode->Sign=n;
- tmpnode->Weight=stat[n];
- // Добавление его в кольцевой список
- AddCListNode(&rootlist,tmpnode);
- };
- };
- if(!rootlist)
- // Если кольцевой список пуст, то и дерево Хаффмана отсутствует
- {
- *root=0;
- };
- // Построение бинарного дерева
- while(!isCListNodeAlone(rootlist))
- // Пока в кольцевом списке более одного элемента
- {
- CListNode*tmp1;
- CListNode*tmp2;
- // Находим два элемента кольцевого списка, ссылающихся на листы/ветви
- // бинарного дерева с наименьшими весами
- GetTwoLeastWeightedNodes(rootlist,&tmp1,&tmp2);
- // Глубины вновь полученных ветвей
- unsigned char dpth1=GetMinTreeDepth(tmp1->TNode);
- unsigned char dpth2=GetMinTreeDepth(tmp2->TNode);
- // Создание и инициализация ветви бинарного дерева Хаффмана
- tmpnode=new TreeNode;
- tmpnode->Left=tmp2->TNode;
- tmpnode->Rght=tmp1->TNode;
- tmpnode->Sign=0;
- tmpnode->Weight=tmp1->TNode->Weight+tmp2->TNode->Weight;
- // Удаление первого найденного элемента из кольцевого списка
- RemoveCListNode(&rootlist,&tmp1);
- // Во втором элементе меняем старый лист/ветвь дерева на новую ветвь
- tmp2->TNode=tmpnode;
- };
- // Результат работы процедуры
- *root=rootlist->TNode;
- // Удаление последнего элемента кольцевого списка
- RemoveCListNode(&rootlist,&rootlist);
- };
- // Удаление дерева Хаффмана
- void RemoveHuffmanTree(TreeNode**root)
- {
- // Текущий элемент
- TreeNode*tmp=*root;
- if(tmp->Left!=0)
- // Если текущий элемент -- ветвь
- {
- // Удалить левую часть дерева
- RemoveHuffmanTree(&(tmp->Left));
- // Удалить правую часть дерева
- RemoveHuffmanTree(&(tmp->Rght));
- };
- // Удалить текущий элемент/ветвь
- delete tmp;
- // Занулить указатель на удалённый элемент
- *root=0;
- };
- // Отображение дерева Хаффмана
- void DisplayHuffmanTree(TreeNode*root,unsigned char numbits,unsigned long bitfield)
- {
- if(root)
- // Если дерево не пусто
- {
- if(root->Left==0)
- // Если текущий элемент -- лист
- {
- // Отобразить вес
- printf("%7d",root->Weight);
- // Отобразить код символа
- unsigned char tmp=root->Sign;
- printf("%5d ",tmp);
- // Отобразить символ
- if(tmp>=14||tmp>=2&&tmp<=6||tmp==11||tmp==12)
- {
- printf("%c",tmp);
- }
- else
- {
- printf(" ");
- };
- // Отобразить длину кода Хаффмана
- printf("%4d ",numbits);
- // Отобразить код Хаффмана
- for(int n=0;n<numbits;n++)
- {
- printf("%d",(bitfield>>(numbits-n-1))&1);
- };
- printf("\n");
- }
- else
- // Если текущий элемент -- ветвь
- {
- // Отобразить подветви
- DisplayHuffmanTree(root->Left,numbits+1,bitfield<<1);
- DisplayHuffmanTree(root->Rght,numbits+1,(bitfield<<1)+1);
- };
- };
- };
- // Отображение дерева Хаффмана 2
- void DisplayHuffmanTree2(TreeNode*root)
- {
- if(root)
- // Если дерево не пусто
- {
- if(root->Left==0)
- // Если текущий элемент -- лист
- {
- printf("0\n");
- unsigned char tmp=root->Sign;
- for(int n=0;n<8;n++)
- {
- printf("%d",(tmp>>n)&1);
- };
- //printf("=%d",tmp);
- printf("\n");
- }
- else
- // Если текущий элемент -- ветвь
- {
- printf("1");
- DisplayHuffmanTree2(root->Left);
- DisplayHuffmanTree2(root->Rght);
- };
- };
- };
- // Инициализация таблицы
- void CreateTable(CodeTableCell**table)
- {
- *table=new CodeTableCell[256];
- unsigned long n;
- for(n=0;n<256;n++)
- {
- (*table)[n].Length=0;
- (*table)[n].Bits=0;
- (*table)[n].Weight=0;
- };
- };
- // Удаление таблицы
- void DeleteTable(CodeTableCell**table)
- {
- delete*table;
- *table=0;
- };
- // Преобразование дерева Хаффмана в таблицу кодов Хаффмана
- void Tree2Table(TreeNode*root,CodeTableCell*table,unsigned char numbits,unsigned long bitfield)
- {
- if(root)
- // Если дерево не пусто
- {
- if(root->Left==0)
- // Если текущий элемент -- лист
- {
- // Сохранить длину
- table[root->Sign].Length=numbits;
- table[root->Sign].Bits=bitfield;
- table[root->Sign].Weight=root->Weight;
- }
- else
- // Если текущий элемент -- ветвь
- {
- // Сохранить подветви
- Tree2Table(root->Left,table,numbits+1,bitfield<<1);
- Tree2Table(root->Rght,table,numbits+1,(bitfield<<1)+1);
- };
- };
- };
- // Возвращает размер закодированных данных в битах
- unsigned long GetEncodedDataSize(CodeTableCell*table)
- {
- unsigned long tmp=0;
- unsigned long n;
- for(n=0;n<256;n++)
- {
- tmp+=table[n].Weight*table[n].Length;
- };
- return tmp;
- };
- // Отображение таблицы кодов Хаффмана
- void DisplayTable(CodeTableCell*table,unsigned char flg)
- {
- unsigned long n;
- for(n=0;n<256;n++)
- {
- if(flg||table[n].Length)
- {
- // Отобразить вес
- printf("%7d",table[n].Weight);
- // Отобразить код символа
- printf("%5d ",n);
- // Отобразить символ
- if(n>=14||n>=2&&n<=6||n==11||n==12)
- {
- printf("%c",n);
- }
- else
- {
- printf(" ");
- };
- // Отобразить длину кода
- printf("%4d ",table[n].Length);
- // Отобразить код Хаффмана
- for(int m=0;m<table[n].Length;m++)
- {
- printf("%d",(table[n].Bits>>(table[n].Length-m-1))&1);
- };
- printf("\n");
- };
- };
- };
- // Подсчёт количества листьев дерева
- unsigned long CountTreeLeaves(TreeNode*root)
- {
- if(root)
- // Если дерево не пусто
- {
- if(root->Left==0)
- // Если текущий элемент -- лист
- {
- return 1;
- }
- else
- // Если текущий элемент -- ветвь
- {
- return CountTreeLeaves(root->Left)+CountTreeLeaves(root->Rght);
- };
- }
- else
- {
- return 0;
- };
- };
- // Сброс упаковки для нового чтения
- void ResetPackage(PackedData*package)
- {
- package->ByteCount2=0;
- package->BitCount2=0;
- };
- // Инициализация упаковки
- void CreatePackage(PackedData*package,unsigned long bytesnum)
- {
- package->BitCount=0;
- package->ByteCount=0;
- ResetPackage(package);
- package->BuffSize=bytesnum;
- package->Buff=new unsigned char[bytesnum];
- for(unsigned long n=0;n<bytesnum;n++)
- {
- package->Buff[n]=0;
- };
- };
- // Деинициализация упаковки
- void DeletePackage(PackedData*package)
- {
- delete package->Buff;
- package->Buff=0;
- package->BitCount=0;
- package->ByteCount=0;
- package->BuffSize=0;
- ResetPackage(package);
- };
- // Упаковка бита
- int PackBit(PackedData*package,unsigned char bit)
- {
- if(package->ByteCount<package->BuffSize)
- {
- package->Buff[package->ByteCount]|=(bit&1)<<package->BitCount;
- package->BitCount++;
- if(package->BitCount>7)
- {
- package->BitCount=0;
- package->ByteCount++;
- };
- return 0;
- }
- else
- {
- return-1;
- };
- };
- // Упаковка байта
- int PackByte(PackedData*package,unsigned char byte)
- {
- if(package->ByteCount<package->BuffSize-1)
- {
- package->Buff[package->ByteCount]|=(byte)<<package->BitCount;
- package->ByteCount++;
- package->Buff[package->ByteCount]|=(byte)>>(8-package->BitCount);
- return 0;
- }
- else
- {
- return-1;
- };
- };
- // Упаковка битовой последовательности
- int PackBitsField(PackedData*package,unsigned char bitsnum,unsigned long bitsfield)
- {
- while(package->ByteCount<package->BuffSize&& // Пока есть место в упаковке
- bitsnum>0) // И есть биты для упаковки
- {
- // Количество битов, помещающихся в текущем байте упаковки
- unsigned char cbn=8-package->BitCount;
- // Если оно больше количества битов, оставшихся для упаковки
- if(cbn>bitsnum)
- {
- // Количество упаковываемых битов равно количеству битов, подлежащих упаковке
- cbn=bitsnum;
- };
- // Поместить текущую пачку бит в упаковку
- package->Buff[package->ByteCount]|=bitsfield<<package->BitCount;
- // Инкрементировать счётчик упакованных битов и байтов если надо
- package->BitCount+=cbn;
- if(package->BitCount>7)
- {
- package->BitCount=0;
- package->ByteCount++;
- };
- // Уменьшить счётчик битов, подлежащих упаковке
- bitsnum-=cbn;
- // Отбросить упакованные биты
- bitsfield>>=cbn;
- };
- if(package->ByteCount<package->BuffSize&&bitsnum==0)
- {
- return 0;
- }
- else
- // Если место в упаковке закончилось, а биты упакованы не все
- {
- // Вернуть ошибку
- return-1;
- };
- };
- // Распаковка бита
- int UnpackBit(PackedData*package,unsigned char*bit)
- {
- if(package->ByteCount2<package->BuffSize)
- {
- *bit=(package->Buff[package->ByteCount2]>>package->BitCount2)&1;
- package->BitCount2++;
- if(package->BitCount2>7)
- {
- package->BitCount2=0;
- package->ByteCount2++;
- };
- return 0;
- }
- else
- {
- return-1;
- };
- };
- // Распаковка байта
- int UnpackByte(PackedData*package,unsigned char*byte)
- {
- if(package->ByteCount2<package->BuffSize-1)
- {
- *byte=package->Buff[package->ByteCount2]>>package->BitCount2;
- package->ByteCount2++;
- *byte|=package->Buff[package->ByteCount2]<<(8-package->BitCount2);
- return 0;
- }
- else
- {
- return-1;
- };
- };
- // Упаковка дерева Хаффмана
- void PackHuffmanTree(TreeNode*root,PackedData*package)
- {
- if(root)
- // Если дерево не пусто
- {
- if(root->Left==0)
- // Если текущий элемент -- лист
- {
- PackBit(package,0);
- PackByte(package,root->Sign);
- }
- else
- // Если текущий элемент -- ветвь
- {
- PackBit(package,1);
- PackHuffmanTree(root->Left,package);
- PackHuffmanTree(root->Rght,package);
- };
- };
- };
- // Распаковка дерева Хаффмана
- void UnpackHaffmanTree(TreeNode**root,PackedData*package)
- {
- *root=new TreeNode;
- (*root)->Weight=0;
- unsigned char tmp;
- UnpackBit(package,&tmp);
- if(tmp)
- // Ветвь
- {
- (*root)->Sign=0;
- UnpackHaffmanTree(&((*root)->Left),package);
- UnpackHaffmanTree(&((*root)->Rght),package);
- }
- else
- // Лист
- {
- (*root)->Left=0;
- (*root)->Rght=0;
- UnpackByte(package,&tmp);
- (*root)->Sign=tmp;
- };
- };
- // Отображение содержимого упаковки в двоичной системе (младшие биты сначала)
- void DisplayPackage(PackedData*package)
- {
- for(unsigned long m=0;m<package->BuffSize;m++)
- {
- //printf("%4X",package.Buff[m]);
- for(int n=0;n<8;n++)
- {
- printf("%d",(package->Buff[m]>>n)&1);
- };
- printf(" ");
- };
- if(package->BuffSize%8)
- {
- printf("\n");
- };
- };
- // Упаковка данных
- void PackData(unsigned long size,unsigned char*data,CodeTableCell*table,PackedData*package)
- {
- unsigned long n;
- for(n=0;n<size;n++)
- {
- unsigned tmp=data[n];
- PackBitsField(package,table[tmp].Length,table[tmp].Bits);
- };
- };
- // Распаковка бита
- unsigned char UnpackChar(TreeNode*root,PackedData*package)
- {
- if(root->Left)
- {
- unsigned char tmp;
- UnpackBit(package,&tmp);
- if(tmp)
- {
- return UnpackChar(root->Left,package);
- }
- else
- {
- return UnpackChar(root->Rght,package);
- };
- }
- else
- {
- return root->Sign;
- };
- };
- // Распаковка данных
- void UnpackData(TreeNode*root,PackedData*package,unsigned long dsize,unsigned char*data)
- {
- ResetPackage(package);
- unsigned long n;
- for(n=0;n<dsize;n++)
- {
- data[n]=UnpackChar(root,package);
- };
- };
- void main()
- {
- // Исходная строка
- //unsigned char data[]="ABRAKADABRA SIMSALABIM";
- unsigned char data[]="Hardly knowing what she did, she picked up a little bit of stick, and held it out to the puppy; whereupon the puppy jumped into the air off all its feet at once, with a yelp of delight, and rushed at the stick, and made believe to worry it; then Alice dodged behind a great thistle, to keep herself from being run over; and the moment she appeared on the other side, the puppy made another rush at the stick, and tumbled head over heels in its hurry to get hold of it; then Alice, thinking it was very like having a game of play with a carthorse, and expecting every moment to be trampled under its feet, ran round the thistle again; then the puppy began a series of short charges at the stick, running a very little way forwards each time and a long way back, and barking hoarsely all the while, till at last it sat down a good way off, panting, with its tongue hanging out of its mouth, and its great eyes half shut.";
- // Размер строки
- unsigned long datasize=0;
- while(data[datasize])
- datasize++;
- printf("String size: %d\n",datasize);
- printf("String: \"%s\"\n\n",data);
- // Встречаемость символов
- unsigned long stat[256];
- GetCharsOccurrence(datasize,data,stat);
- // Указатель на корень дерева Хаффмана
- TreeNode*root;
- // Создание дерева Хаффмана
- MakeHuffmanTree(stat,&root);
- // Отображение дерева Хаффмана
- printf("Huffnam tree:\n");
- printf(" Weight Code Char Sz Huffman Key\n");
- DisplayHuffmanTree(root,0,0);
- printf("Leaves number: %d\n\n",CountTreeLeaves(root));
- // Упаковка для дерева Хаффмана
- PackedData tree_package;
- // Упаковка дерева Хаффмана
- unsigned long ctl=CountTreeLeaves(root);
- CreatePackage(&tree_package,(5*ctl)/4+2);
- //DisplayHuffmanTree2(root);
- PackHuffmanTree(root,&tree_package);
- // Отображение упакованных данных
- printf("Packed Huffman Tree:\n");
- DisplayPackage(&tree_package);
- printf("Bytes: %d, bits: %d\n\n",tree_package.ByteCount,tree_package.BitCount);
- // Распаковка дерева
- TreeNode*newroot;
- UnpackHaffmanTree(&newroot,&tree_package);
- printf("Unpacked Huffnam tree:\n");
- printf(" Weight Code Char Sz Huffman Key\n");
- DisplayHuffmanTree(newroot,0,0);
- printf("Leaves number: %d\n\n",CountTreeLeaves(newroot));
- CodeTableCell*table;
- // Работа с таблицей кодов Хаффмана
- CreateTable(&table);
- Tree2Table(root,table,0,0);
- printf("Shortened Huffnam code table:\n");
- printf(" Weight Code Char Sz Huffman Key\n");
- DisplayTable(table,0);
- unsigned long eds=GetEncodedDataSize(table);
- printf("Encoded data size: %d byte, last byte: %d bits\n\n",eds/8+(eds%8!=0),eds%8);
- // Упаковка данных
- PackedData data_package;
- CreatePackage(&data_package,eds/8+(eds%8!=0));
- PackData(datasize,data,table,&data_package);
- printf("Packed Data:\n");
- DisplayPackage(&data_package);
- // Распаковка данных
- unsigned char*unpackeddata=new unsigned char[datasize+1];
- unpackeddata[datasize]=0;
- UnpackData(newroot,&data_package,datasize,unpackeddata);
- printf("Unpacked string: \"%s\"\n\n",data);
- // Удаление всего
- DeletePackage(&data_package);
- DeleteTable(&table);
- RemoveHuffmanTree(&newroot);
- DeletePackage(&tree_package);
- RemoveHuffmanTree(&root);
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement