香农码怎么编码

香农码怎么编码,第1张

1、确定字符的出现概率:在进行香农编码之前,需要统计文本或数据流中每个字符出现的频率,并计算出它们的出现概率。

2、构建编码树:根据字符的出现概率,构建一棵二叉树,每个字符对应一个叶子节点。出现概率越高的字符在树中的深度越浅。

3、进行编码:从根节点开始,对于每个字符,向左走表示编码0,向右走表示编码1,直到达到对应的叶子节点。这样,每个字符都可以用一个唯一的二进制码表示。

4、解码:根据编码树和二进制码,可以快速解码出原始文本或数据流。

#include"iostream.h"

#include<iomanip.h>

#include"vector"

#include"algorithm"

#include"math.h"

using namespace std

struct bitree

{//定义结构用于存储编码结果的二叉树结构,在译码时用到

char ch //用于存储码符号

char mz //用于存储码字

bitree * lchild

bitree * rchild

}

struct data

{//用于存储相关的信源符号以及其概率

double p

char ch

vector<char>code

int ml

}

bool sortspecial(data dt1,data dt2)

{//用于排序时用

return dt1.p>dt2.p

}

void print2(vector<char>vd)

{//用于打印译码结果

for(int i=0i<vd.size()i++)

cout<<vd[i]<<" "

cout<<endl

}

void read(vector <data>&vd)

{//用于读入相关的信源符号以及概率

int n

while(true)

{

cout<<"请输入信源符号数:"

cin>>n

cout<<"请输入相应的信源符号及其概率:"<<endl

data dt

int i=0

while(i<n)

{

cin>>dt.ch

cin>>dt.p

dt.ml=0

vd.push_back(dt)

i++

}

double sum=0

vector<data>::iterator pit

/* for(pit=vd.begin()pit!=vd.end()pit++)

{

sum+=pit->p

}

if(sum!=1)

{

cout<<"你输入的概率不符合要求,请重新输入."<<endl

sum=0

continue

}*/

sort(vd.begin(),vd.end(),sortspecial)

break

}

}

void append(char ch1,char ch2,bitree *&bt)

{//用于再构造码字二叉树时向其中添加结点

bitree * bit=new bitree

bit->ch=ch1

bit->mz=ch2

bit->lchild=NULL

bit->rchild=NULL

if(ch1=='0')

bt->rchild=bit

else bt->lchild=bit

}

void Creatmz1(vector<data>&vd,int begin1,int end1 ,double pn ,bitree *&bt)

{//进行编码,用递归的方法进行编码

int begin=begin1,end=end1

if(begin==end) return

else if(begin+1==end)

{

return

}

else if(begin+2==end){

vd[begin].code.push_back('0')

vd[begin].ml++

append('0',vd[begin].ch,bt)

vd[end-1].code.push_back('1')

vd[end-1].ml++

append('1',vd[end-1].ch,bt)

return

}

else{

double sum0=0,sum1=0,sum2=0

do{

sum1+=vd[begin].p

sum2=sum1+vd[begin+1].p

begin++

}while(fabs(sum1/pn-0.5)>fabs(sum2/pn-0.5))//用于找到上下两组码的分点使得其概率和近于相同

for(int i=begin1i<begini++){

vd[i].code.push_back('0')

vd[i].ml++

}

if(begin1+1 == begin){

append('0',vd[begin1].ch,bt)

}

else append('0','0',bt)

for(int j=beginj<=end1-1j++){

vd[j].code.push_back('1')

vd[j].ml++

}

if(begin+1 == end1){

append('1',vd[begin].ch,bt)

}

else append('1','0',bt)

Creatmz1(vd,begin1 ,begin,sum1,bt->rchild )//对分点前的进行编码

Creatmz1(vd,begin ,end1,pn-sum1,bt->lchild)//对分点后的进行编码*/

}

}

void print1(vector<data>vd)

{//用于打印编码结果

cout<<"xi"<<setw(8)<<"P(xi)"<<setw(8)<<"码长"

<<setw(8)<<"码字"<<setw(8)<<endl

for(int i=0i<vd.size()i++){

cout<<vd[i].ch<<setw(8)<<vd[i].p<<setw(8)<<vd[i].ml<<setw(8)

for(int j=0j<vd[i].code.size()j++)

cout<<vd[i].code[j]

cout<<setw(8)<<endl

}

}

void clear(bitree * &bt)

{//对二叉树的动态存储空间进行释放

if(bt!=NULL&&bt->lchild!=NULL)

clear(bt->lchild)

if(bt!=NULL&&bt->rchild!=NULL)

clear(bt->rchild)

delete bt

}

bool des_code(vector <char>&vr,vector <char>vt,bitree *bt)

{//用二叉编码树进行解码

if(bt==NULL)

{

cout<<"码树不存在!!!"<<endl

return false

}

int pit=0

bitree * mbt=bt

while ((mbt->lchild!=NULL||mbt->rchild!=NULL)||pit<vt.size())

{

if(mbt->lchild==NULL&&mbt->rchild==NULL&&mbt->mz!='0')

{

vr.push_back(mbt->mz)

mbt=bt

}

if(mbt->lchild!=NULL&&vt[pit]=='1')

{

mbt=mbt->lchild

pit++

}

else if(mbt->rchild!=NULL&&vt[pit]=='0')

{

mbt=mbt->rchild

pit++

}

else if(mbt->lchild!=NULL&&mbt->rchild!=NULL) break

}

if(mbt->lchild!=NULL&&mbt->rchild!=NULL)

{

cout<<"你输入的是一个错误的码序列,请较正后再输入."<<endl

return false

}

else {

vr.push_back(mbt->mz)

return true

}

}

void read1(vector<char>&vd)

{//用于读入要解码的序列

cout<<"请输要译码的序列(以'#'结束):"<<endl

char dt

int i=0

cin>>dt

while(dt!='#')

{

vd.push_back(dt)

cin>>dt

}

}

void print_H_L_R(vector<data>vd)

{//用于计算并打印信息熵,平均码长,效率

double H=0,L=0,R=0

for(int i=0i<vd.size()i++)

{

H+=vd[i].p*(log10(1/vd[i].p)/log10(2))

L+=vd[i].p*(double)vd[i].ml

}

R=H/L

cout<<"此码的信息熵(H)是:"<<H<<endl

cout<<"此码的平均码长(L)为:"<<L<<endl

cout<<"此码的效率(U)为:"<<R<<endl

}

int main()

{

bitree * bt=new bitree

bt->ch = '#'

bt->mz = '*'

bt->lchild=NULL

bt->rchild=NULL

vector <data>vd

vector <char>vr

vector <char>vt

cout<<"************下面将对Fano编,译码的过程进行演示*************"<<endl

cout<<"__________________________________________________________"<<endl

cout<<endl

cout<<"************下面显示编码的过程及相关参数和结果************"<<endl

read(vd)

if(vd.size()==1)

{

vd[0].code.push_back('0')

vd[0].ml++

append('0',vd[0].ch,bt)

}

cout<<endl

Creatmz1(vd,0,vd.size(),1,bt)

cout<<"**************编码结果**************"<<endl

print1(vd)

print_H_L_R(vd)

cout<<endl

cout<<"************ 下面将进行译码过程 *** 作的演示 ************"<<endl

cout<<endl

read1(vt)

if(des_code(vr,vt,bt))

print2(vr)

clear(bt)

return 1

}

一定要提高悬赏分哟。

//赫夫曼编码程序(严蔚敏数据结构)

#include <iostream>

using namespace std

typedef struct

{

int weight

int parent,lchild,rchild

}HTNode,*HuffmanTree

typedef char **HuffmanCode

typedef char *EachHuffcode

void Select(HuffmanTree HT,int length,int &s1,int &s2)

{

//s1 lowest,s2 lower

unsigned int min = 5000

HuffmanTree p = HT

int i

for(i = 1, ++pi <= length ++i,++p)

{

if(p->weight <min &&p->parent == 0)

{

min = p->weight

s1 = i

}

}

min = 5000

p = HT

//Get the second less weight

for(i = 1, ++pi <= length ++i,++p)

{

if(p->weight <min &&p->parent == 0)

{

if( i == s1)//case s1,ignore

continue

min = p->weight

s2 = i

}

}

}

void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC, int *w,int n)

{

if(n <= 1)

return

int m = 2 * n - 1

HT = new HTNode[m + 1]//0 is not used

HuffmanTree p = HT

int i

for( i = 1, ++pi <= n++i,++p,++w)

{

p->weight = *w//NOte: never use this *p = {*w,0,0,0,0},because *p has already been declared

p->parent = p->lchild = p->rchild = 0

}

for(i <= m++i,++p)

p->weight = p->parent = p->lchild = p->rchild = 0

int s1

int s2

for( i = n + 1i <= m++i)

{

Select(HT,i-1,s1,s2)

HT[s1].parent = i

HT[s2].parent = i

HT[i].lchild = s1

HT[i].rchild = s2

HT[i].weight = HT[s1].weight + HT[s2].weight

}

HC = new EachHuffcode[n+1]//0 is not used

char *cd = new char[n]

cd[n-1] = '\0'//the end of each char

int start

for(int i = 1i <= n ++i)

{//get each huff code for h[1] to h[n]

start = n -1

for(int c = i, int f = HT[i].parentf != 0c = f ,f = HT[f].parent)

if(c == HT[f].lchild) cd[--start] = '0'

else cd[--start] = '1'

HC[i] = new char[n - start]//allocate memory for each HT

strcpy(HC[i],&cd[start])

}

delete []cd//don't forget release memory

}

int main(int argc, char* argv[])

{

HuffmanTree hftree = NULL

HuffmanCode hfcode = NULL

int weight[4] = {7,5,2,4}//four node's weight

HuffmanCoding(hftree,hfcode,weight,4)

EachHuffcode *p = hfcode

++p

for (int i = 0i <4++i,++p)

{

cout<<*p<<endl//show each huffman code by each line

}

for(int i = 1i <=4++i)

delete hfcode[i]//release memory

delete []hfcode

delete []hftree

return 0

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/11622221.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-17
下一篇2023-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存