数据结构-Huffman树
生活随笔
收集整理的這篇文章主要介紹了
数据结构-Huffman树
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Huffman樹的編碼和解碼
思想:1.統(tǒng)計字符串每個字母出現(xiàn)的個數(shù)2.依次取出兩個最小的字母進行合并(分別作為左右子節(jié)點,另左子節(jié)點<右子節(jié)點的值),使用他們值之和作為根節(jié)點的值,并將根節(jié)點加入到未合并的節(jié)點序列中。重復1,2操作,直到?jīng)]有兩個節(jié)點可以合并為止。
#include<iostream> #include<iostream> #include<map> #include<vector> using namespace std; map<int,string> pp;//將int類型轉(zhuǎn)化為對應Huffman樹中的string,但是只能用于單一元的才行 map<char,int> p;//將字符轉(zhuǎn)化為int類型 int len;//所得字符的個數(shù). struct huffmannode{float data;string ss;huffmannode*leftchild,*rightchild,*parent;huffmannode(float a=0,huffmannode* b=NULL,huffmannode* c=NULL,huffmannode* d=NULL,string s=""){ss=s;data=a;leftchild=b,rightchild=c,parent=d;} };bool operator>= (huffmannode& io,huffmannode& p){return io.data>p.data?true:false; } bool operator<=(huffmannode& io,huffmannode& op){return io.data<op.data?true:false; }template<class T> class minheap{ public:minheap(int sz=20){//建立空堆。只是給了內(nèi)存空間沒有數(shù)據(jù)值。maxheapsize=sz>20?sz:20;heap=new T[maxheapsize];if(heap==NULL){cout<<"內(nèi)存分配錯誤."<<endl;exit(1);}currentsize=0;}minheap(T arr[],int n){maxheapsize=n>20?n:20;heap=new T[maxheapsize];if(heap==NULL){cerr<<"堆存儲空間分配失敗!"<<endl;exit(1);}for(int i=0;i<n;i++){heap[i]=arr[i];}currentsize=n;int currentpos=(currentsize-2)/2;//第一個節(jié)點位置while(currentpos>=0){siftdown(currentpos,currentsize-1);currentpos--;}};~minheap(){delete [] heap;}bool removemin(T& x);//刪除堆頂元素.bool isempty(){//當當前指針指向堆首時就為真,即沒有元素.if(currentsize==0){return true;}else{return false;}}bool isfull(){if(currentsize>=maxheapsize){return true;}else{return false;}}void makeempty(){currentsize=0;}bool insert(const T& io);void output(){int i=0;while(i<currentsize){cout<<heap[i++]<<" ";}} private:T *heap;int currentsize;int maxheapsize;void siftdown(int start,int m);void siftup(int start); }; template<class T> void minheap<T>::siftdown(int start,int m){int i=start;T io=heap[i];T change;int j=2*i+1;//當前節(jié)點的左孩子節(jié)點while(j<=m){if(j+1<=m&&heap[j+1]<=heap[j]){change=heap[j+1];heap[j+1]=heap[j];heap[j]=change;}if(heap[j]>=io){break;}else{heap[i]=heap[j];i=j;j=j*2+1;}}heap[i]=io; } template<class T> void minheap<T>::siftup(int start){int j=start,i=(j-1)/2;T temp=heap[j];while(j>0){if(heap[i]>=heap[j]){heap[j]=heap[i];j=i;i=(i-1)/2;}else{break;}}heap[j]=temp; } template<class T> bool minheap<T>::insert(const T& io){if(currentsize==maxheapsize){return false;}else{heap[currentsize]=io;siftup(currentsize);currentsize++;return true;} } template<class T> bool minheap<T>::removemin(T&x){if(currentsize==0){return false;}else{x=heap[0];heap[0]=heap[currentsize-1];currentsize--;siftdown(0,currentsize-1);return true;}// } class huffmantree{ private:huffmannode *root;void deletetree(huffmannode* t); public:void mergetree(huffmannode*& parent1,huffmannode* first,huffmannode* second){parent1=new huffmannode(first->data+second->data);parent1->leftchild=first,parent1->rightchild=second;first->parent=parent1;second->parent=parent1;}huffmantree(float *w=NULL,int n=0){minheap<huffmannode> hp;huffmannode *first,*second,work;huffmannode *parent1;for(int i=0;i<n;i++){work.data=w[i];work.leftchild=NULL,work.rightchild=NULL,work.parent=NULL;hp.insert(work);}for(int i=0;i<n-1;i++){//通過個數(shù)限定解決可能first和second無值的情況.注意removemin返回的是bool類型,first=new huffmannode;second= new huffmannode;hp.removemin(*first);hp.removemin(*second);mergetree(parent1,first,second);hp.insert(*parent1);//insert是插入到最小堆中所以他的第一和第二小元素是有先后順序的}root=parent1;//將最終的父節(jié)點賦值給root節(jié)點.}huffmannode* getroot(){return root;}void bianma(huffmannode*&op){//根節(jié)點初始化為空字符串if(op==NULL){return;}if(op->rightchild==NULL&&op->leftchild==NULL){//尾節(jié)點就是我們要的解,即編碼后的字符串.pp[op->data]=op->ss;return;//記得返回,因為之后為NULL了但是又沒有判斷條件}if(op->leftchild!=NULL){op->leftchild->ss=op->ss+"0";}if(op->rightchild!=NULL){op->rightchild->ss=op->ss+"1";}bianma(op->leftchild);bianma(op->rightchild);}void jiema(string oo,vector<char> &io,string op,int left){//不能直接使用io的長度因為可能長度過長,不是他的實際長度if(left==op.length()){//這種條件下,如果滿足了會回到原來的位置,cout<<oo<<endl;//可能存在多種解return;}for(int i=0;i<len;i++){if(op.substr(left,(pp[p[io[i]]]).size())==pp[p[io[i]]]){oo+=io[i];int cnt=left;cnt+=pp[p[io[i]]].size();//因為從0開始jiema(oo,io,op,cnt);//使用這樣的局部變量才能在這次滿足之后下一個循環(huán)再使用時為原來的起始值。。}}return;//表示失敗時自動返回} }; void output(huffmannode&op) {if (op.data == 0)return;cout << op.data << endl;if (op.leftchild == NULL) {cout << "true" << endl;}cout << (*op.leftchild).data << endl;output(*op.leftchild);output(*op.rightchild); } int main() {string str;cin >> str;for (int i = 0; i < str.length(); i++) {if (!p.count(str[i])) {p[str[i]] = 1;} else {p[str[i]]++;}}map<char, int>::iterator io = p.begin();float *i = new float[100];vector<char> ent(str.length(), 0);for (; io != p.end(); io++) {i[len] = io->second;ent[len] = io->first;cout << i[len] << endl;len++;}huffmantree ip(i, len);huffmannode *end = ip.getroot();//Huffman編碼ip.bianma(end);for (int k = 0; k < len; k++) {cout << ent[k] << "的編碼為" << pp[p[ent[k]]] << endl;}string iop;cin >> iop;string re = "";//Huffman解碼ip.jiema(re, ent, iop, 0);return 0; }求解字符串隊列哈夫曼序列的長度
#include <bits/stdc++.h> //萬能頭文件,vs2019中需自己設置 using namespace std; string s; map<char, int> mp; priority_queue<int, vector<int>, greater<int>> q; //升序排列int main() {getline(cin, s);int len = s.length();for (int i = 0; i < len; i++) { //記錄字符與其對應的出現(xiàn)的次數(shù)if (mp.find(s[i]) == mp.end()) {mp[s[i]] = 1;} else {mp[s[i]]++;}}for (map<char, int>::iterator it = mp.begin(); it != mp.end(); it++) {q.push(it->second); //字符出現(xiàn)的次數(shù)入隊}int ans = 0;//記錄結果while (q.size() != 1) {int a, b, temp;//a,b記錄最小的兩個次數(shù)a = q.top();q.pop();b = q.top();q.pop();temp = a + b; //隊列中最小的兩個次數(shù)相加ans += temp;q.push(temp);//最小的兩個次數(shù)相加再次入隊,優(yōu)先隊列自行排序}cout << ans << endl;return 0; }總結
以上是生活随笔為你收集整理的数据结构-Huffman树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构-单链表实现
- 下一篇: 数据结构-链表栈