经验证解压缩前与解压缩后文本一致,无出入
binaryTreeNode.h
linkedBinaryTree.h
源.cpp
binaryTreeNode.h
#ifndef binaryTreeNode_
#define binaryTreeNode_
#include
#include
#include
using namespace std;
template <class T>
struct binaryTreeNode
{
int *character;
string element;
binaryTreeNode<T> *leftChild, // left subtree
*rightChild; // right subtree
binaryTreeNode() {
element = "";
character = nullptr;
leftChild = rightChild = NULL;
}
binaryTreeNode(
binaryTreeNode *theLeftChild,
binaryTreeNode *theRightChild)
{
element = "";
character = nullptr;
leftChild = theLeftChild;
rightChild = theRightChild;
}
binaryTreeNode(int c) {
element = "";
character = new int(c);
leftChild = rightChild = NULL;
}
};
#endif
#pragma once
linkedBinaryTree.h
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "binaryTreeNode.h"
using namespace std;
template <class E>
class linkedBinaryTree {
public:
binaryTreeNode<E> *root;
int treeSize;
linkedBinaryTree() { root = nullptr; treeSize = 0; }
bool empty() {
if (this->treeSize == 0)return 1;
return 0;
}
map<char, string> huffmanMap;
void makeTree(
linkedBinaryTree<E>&, linkedBinaryTree<E>&);
void makeTree(int i);
void visit2(binaryTreeNode<E>*t);
int count;
void preOrder(binaryTreeNode<E> *t);
void toMap(binaryTreeNode<E>*t);
static void output(binaryTreeNode<E> *t)
{
cout << t->element << ' ';
}
void printMap();
void zip(string a, string b);
};
template<class T>
class huffmanNode {
public:
linkedBinaryTree<int> *tree;
T weight;
operator T () const { return weight; }
huffmanNode() {
weight = 0;
tree = new linkedBinaryTree<T>;
}
};
template<class E>
void visit(binaryTreeNode<E>*t) {
cout << t->element;
cout << endl;
}
template<class T>
class minHeap
{
public:
minHeap(int initialCapacity = 10);
~minHeap() { delete[] heap; }
bool empty() const { return heapSize == 0; }
int size() const
{
return heapSize;
}
const T& top()
{// return min element
if (heapSize == 0)
{
cout << "empty" << endl;
}
return heap[1];
}
void pop();
void push(const T&);
void initialize(T *, int);
void deactivateArray()
{
heap = NULL; arrayLength = heapSize = 0;
}
void output(ostream& out) const;
private:
int heapSize; // number of elements in queue
int arrayLength; // queue capacity + 1
T *heap; // element array
};
template<class T>
minHeap<T>::minHeap(int initialCapacity)
{// Constructor.
if (initialCapacity < 1)
{
ostringstream s;
s << "Initial capacity = " << initialCapacity << " Must be > 0";
}
arrayLength = initialCapacity + 1;
heap = new T[arrayLength];
heapSize = 0;
}
template<class T>
void minHeap<T>::push(const T& theElement)
{// Add theElement to heap.
// increase array length if necessary
if (heapSize == arrayLength - 1)
{// double array length
cout << "full" << endl;
return;
}
// find place for theElement
// currentNode starts at new leaf and moves up tree
int currentNode = ++heapSize;
while (currentNode != 1 && heap[currentNode / 2] > theElement)
{
// cannot put theElement in heap[currentNode]
heap[currentNode] = heap[currentNode / 2]; // move element down
currentNode /= 2; // move to parent
}
heap[currentNode] = theElement;
}
template<class T>
void minHeap<T>::pop()
{// Remove max element.
// if heap is empty return null
if (heapSize == 0) // heap empty
{
cout << "empty" << endl;
return;
}
// Delete min element
heap[1].~T();
// Remove last element and reheapify
T lastElement = heap[heapSize--];
// find place for lastElement starting at root
int currentNode = 1,
child = 2; // child of currentNode
while (child <= heapSize)
{
// heap[child] should be smaller child of currentNode
if (child < heapSize && heap[child] > heap[child + 1])
child++;
// can we put lastElement in heap[currentNode]?
if (lastElement <= heap[child])
break; // yes
// no
heap[currentNode] = heap[child]; // move child up
currentNode = child; // move down a level
child *= 2;
}
heap[currentNode] = lastElement;
}
template<class T>
void minHeap<T>::initialize(T *theHeap, int theSize)
{// Initialize max heap to element array theHeap[1:theSize].
delete[] heap;
heap = theHeap;
heapSize = theSize;
// heapify
for (int root = heapSize / 2; root >= 1; root--)
{
T rootElement = heap[root];
// find place to put rootElement
int child = 2 * root; // parent of child is target
// location for rootElement
while (child <= heapSize)
{
// heap[child] should be smaller sibling
if (child < heapSize && heap[child] > heap[child + 1])
child++;
// can we put rootElement in heap[child/2]?
if (rootElement <= heap[child])
break; // yes
// no
heap[child / 2] = heap[child]; // move child up
child *= 2; // move down a level
}
heap[child / 2] = rootElement;
}
}
template<class T>
void minHeap<T>::output(ostream& out) const
{// Put the array into the stream out.
copy(heap + 1, heap + heapSize + 1, ostream_iterator<T>(cout, " "));
}
// overload <<
template <class T>
ostream& operator<<(ostream& out, const minHeap<T>& x)
{
x.output(out); return out;
}
//judge this node if leaf or not
template<class T>
bool f(binaryTreeNode<T>*n) {
if (n->leftChild == nullptr&&n->rightChild == nullptr)
return 1;
return 0;
}
// template
// int linkedBinaryTree::size() {
// return this->treeSize;
// }
// template
// E* linkedBinaryTree::rootElement() const
// {// Return NULL if no root. Otherwise, return pointer to root element.
// if (treeSize == 0)
// return nullptr; // no root
// else
// return &root->element;
// }
template<class E>
void linkedBinaryTree<E>::makeTree(int i) {
root = new binaryTreeNode<E>(i);
treeSize++;
return;
}
template<class E>
void linkedBinaryTree<E>::makeTree(linkedBinaryTree<E>& left, linkedBinaryTree<E>& right)
{// Combine left, right, and element to make new tree.
// left, right, and this must be different trees.
// create combined tree
root = new binaryTreeNode<E>(left.root, right.root);
treeSize = left.treeSize + right.treeSize + 1;
// deny access from trees left and right
left.root = right.root = nullptr;
left.treeSize = right.treeSize = 0;
}
template<class E>
void linkedBinaryTree<E>::preOrder(binaryTreeNode<E> *t)
{// Preorder traversal.
if (t != nullptr)
{
visit(t);
preOrder(t->leftChild);
preOrder(t->rightChild);
}
}
template<class E>
void postOrder(binaryTreeNode<E> *t)
{// Postorder traversal.
if (t != nullptr)
{
postOrder(t->leftChild);
postOrder(t->rightChild);
visit(t);
}
}
template<class E>
void linkedBinaryTree<E>::toMap(binaryTreeNode<E>*t) {
if (t != nullptr)
{
toMap(t->leftChild);
toMap(t->rightChild);
visit2(t);
}
}
template<class T>
void show(binaryTreeNode<T> *x, int d) {
if (x != NULL) {
show(x->rightChild, d + 1);
cout << setw(5 * d) << " " << x->element << endl;
show(x->leftChild, d + 1);
}
}
//translate charachter to 01 string
template<class T>
void element_tanslate(binaryTreeNode<T>*t, string a) {
if (t->character != nullptr)
{
t->element = a;
return;
}
if (t->leftChild)
{
a += '0';
element_tanslate(t->leftChild, a);
}
a.pop_back();// most point!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (t->rightChild) {
a += '1';
element_tanslate(t->rightChild, a);
}
a.pop_back();
return;
}
template<class E>
void linkedBinaryTree<E>::visit2(binaryTreeNode<E>*t) {
if (t->character != nullptr) {
char a = (char)(*t->character);
huffmanMap.insert(map<char, string>::value_type(a, t->element));
}
}
//print map on screen
template<class E>
void linkedBinaryTree<E>::printMap() {
map<char, string>::iterator it;
for (it = huffmanMap.begin(); it != huffmanMap.end(); ++it)
{
cout << it->first;
cout << it->second;
cout << endl;
}
}
//print map in file
//zip
template<class E>
void linkedBinaryTree<E>::zip(string zip_before, string zip_after) {
ifstream f_zip_before(zip_before, ios::in);
ofstream f_zip_after(zip_after, ios::out | ios::binary | ios::app);
string sum = "";
while (f_zip_before.peek() != EOF)
{
char m1;
f_zip_before.get(m1);
string s = huffmanMap[m1];
//this is the point
sum += s;
}
//print zip after
cout << "----------------------zip after-----------------------" << endl;
cout << sum << endl << endl;
int a = floor(sum.length() / 8), b = sum.length() % 8;
f_zip_after.write((char*)&a, sizeof(int));
f_zip_after.write((char*)&b, sizeof(int));
for (int i = 0; i < sum.length(); i += 8) {
bitset<8> a(sum, i, i + 8);
f_zip_after.write((char*)&a, sizeof(bool));
if ((i + 8) > sum.length())
{
bitset<8> a(sum, i, sum.length());
f_zip_after.write((char*)&a, sizeof(bool));
break;
}
}
f_zip_after.close();
f_zip_before.close();
}
//unzip
string Expend(string txt, binaryTreeNode<int>*t) {
string re = "";
for (int i = 0; i < txt.length(); i) {
// most point!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
binaryTreeNode<int> *x = t;
while (!f<int>(x)) {
if (txt[i] == '0')
x = x->leftChild;
else if (txt[i] == '1')
x = x->rightChild;
i++;
}
re += (char)*x->character;
x = t;
}
return re;
}
void unzip(string unzip_before, string unzip_after) {
ifstream f_unzip_before(unzip_before, ios::in | ios::binary);
ofstream f_unzip_after(unzip_after, ios::out);
//read the charachters categroies
int count;
//read characters
f_unzip_before.read((char*)&count, sizeof(int));
int *charachters = new int[count];
int *weight = new int[count];
for (int i = 0; i < count; i++) {
f_unzip_before.read((char*)&charachters[i], sizeof(int));
}
for (int i = 0; i < count; i++)
f_unzip_before.read((char*)&weight[i], sizeof(int));
//creat huffmantree
huffmanNode<int> *hNode = new huffmanNode<int>[count];
minHeap<huffmanNode<int>> heap(count);
for (int i = 0; i < count; i++)
{
hNode[i].weight = weight[i];
hNode[i].tree = new linkedBinaryTree<int>;
hNode[i].tree->makeTree(charachters[i]);
heap.push(hNode[i]);
}
// repeatedly combine trees from min heap
// until only one tree remains
huffmanNode<int> w, x, y;
linkedBinaryTree<int> *z;
for (int i = 1; i < count; i++)
{
// remove two lightest trees from the min heap
x = heap.top(); heap.pop();
y = heap.top(); heap.pop();
// combine into a single tree
z = new linkedBinaryTree<int>;
z->makeTree(*x.tree, *y.tree);
w.weight = x.weight + y.weight;
w.tree = z;
heap.push(w);
delete x.tree;
delete y.tree;
}
//read the zip code
string sum = "";
int times, b;
f_unzip_before.read((char*)×, sizeof(int));
f_unzip_before.read((char*)&b, sizeof(int));
for (int i = 0; i < times; i++) {
bitset<8> d;
f_unzip_before.read((char*)&d, sizeof(bool));
sum += d.to_string();
}
bitset<8> d;
f_unzip_before.read((char*)&d, sizeof(bool));
string k = d.to_string();
for (int i = 8 - b; i < 8; i++)
sum += k[i];
// test get zip_after code whether rigth or not
cout << "----------------------------------get from zip file---------------------------" << endl;
cout << sum << endl << endl;
int q = 0;
binaryTreeNode<int> *t = heap.top().tree->root;
element_tanslate(t, "");
cout << "解压时的树" << endl;
show<int>(t, 5);
cout << "end" << endl;
string unzip = Expend(sum, t);
f_unzip_after << unzip;
f_unzip_after.close();
f_unzip_before.close();
}
#pragma once
源.cpp
#include
#include
#include
#include"linkedBinaryTree.h"
#include
#include
#include
using namespace std;
int countCharacter[200];
int cmp(const pair<int, int>& x, const pair<int, int>& y)
{
return x.second < y.second;
}
template <class T>
linkedBinaryTree<int>* huffmanTree(T weight[], int n, string s)
{// Generate Huffman tree with weights weight[1:n], n >= 1.
// create an array of single node trees
int count = 0; map<int, int, greater<int> > show_map_ans;
for (int i = 0; i < n; i++)
if (weight[i])count++;
huffmanNode<T> *hNode = new huffmanNode<T>[count + 1];
int q = 1;
for (int i = 0; i < n; i++) {
if (weight[i]) {
//print pre character times
cout << (char)i << " " << i << " " << weight[i] << endl;
show_map_ans.insert(map<int, int>::value_type(i, weight[i]));
hNode[q].weight = weight[i];
hNode[q].tree = new linkedBinaryTree<int>;
hNode[q].tree->makeTree(i);
q++;
}
}
int *a = new int[count];
int *b = new int[count];
typedef pair<int, int> PAIR;
vector<PAIR> show_map_ans_vec(show_map_ans.begin(), show_map_ans.end());//put map element into vector
sort(show_map_ans_vec.begin(), show_map_ans_vec.end(), cmp);//use sort
for (int i = 0; i != show_map_ans_vec.size(); ++i) {//show element
a[i] = (int)show_map_ans_vec[i].first;
b[i] = (int)show_map_ans_vec[i].second;
/*cout<
}
ofstream ofile2(s, ios::in | ios::binary);
ofile2.write((char*)&count, sizeof(int));
for (int it = 0; it < count; it++)
{
ofile2.write((char*)&a[it], sizeof(int));
}
for (int it = 0; it < count; it++)
ofile2.write((char*)&b[it], sizeof(int));
ofile2.close();
// make node array into a min heap
minHeap<huffmanNode<T> > heap(count);
heap.initialize(hNode, count);
//test minHeap
//for (int i = 0; i < count; i++)
//{
// huffmanNode m = heap.top();
// cout << *m.tree->root->character << endl;
// heap.pop();
//}
// repeatedly combine trees from min heap
// until only one tree remains
huffmanNode<T> w, x, y;
linkedBinaryTree<int> *z;
for (int i = 1; i < count; i++)
{
// remove two lightest trees from the min heap
x = heap.top(); heap.pop();
y = heap.top(); heap.pop();
// combine into a single tree
z = new linkedBinaryTree<int>;
z->makeTree(*x.tree, *y.tree);
w.weight = x.weight + y.weight;
w.tree = z;
heap.push(w);
delete x.tree;
delete y.tree;
}
// destructor for min heap deletes hNode
return heap.top().tree;
}
int main(void)
{
ifstream infile("zip_before.txt");
//initialization countCharachter
for (int i = 0; i < 200; i++)
countCharacter[i] = 0;
//pre charachter read file
char c;
if (infile.peek() == EOF)
{
cout << "this file is empty!!!" << endl;
exit(1);
}
while (infile.peek() != EOF)
{
infile.get(c);
countCharacter[c]++;
}
infile.close();
//build huffmanTree
cout << "-------------------print charachters the file has and occure times--------------" << endl;
linkedBinaryTree<int> *x = huffmanTree(countCharacter, 200, "zip_after.txt");
//print
cout << endl << endl;
cout << "-----------------print huffmanTree postOrder-----------------" << endl;
/*vector> a;*/
/*.push_back(0);*/
element_tanslate(x->root, "");
cout << "打印压缩时的树" << endl;
show<int>(x->root, 5);
cout << "-------------print map------------" << endl;
x->toMap(x->root);
x->printMap();
//x->printMap_tofile("zip_after_map.bat");
x->zip("zip_before.txt", "zip_after.txt");
//
unzip("zip_after.txt", "unzip_after.txt");
return 0;
}