香农编码简单例题_单链表逆序输出c语言
常量介紹:
si:信源符號
p(si):該項概率
pi:前i-1項累加概率 p(s1)+p(s2)+…+p(s(i-1))
li:碼長,計算公式[
-log(p(si))]+1 ;(下取整)
求解步驟:
1、將信源符號按從大到小的順序排列
2、求碼長li
3、求累加概率pi
4、將累加概率pi轉換為二進制小數,并根據碼長li取小數點后li為作為碼字
介紹:
本程序是將原始數據存放到記事本
Data.txt中,記事本應與.cpp文件放入同一文件目錄下,然后再程序中讀取記事本內數據進行香農編碼。
記事本:
介紹:
名稱為:Data.txt
內容:第一行:”s p(si)”,且內容以空格隔開,注意換行
實例圖片:
頭文件:
#include
#include
#include
using namespace std;
單鏈表結構體聲明:
typedef struct LinkList //單鏈表結構體
{
string Mark; //符號s
double P; //概率
double SumP; //累加概率
int CodeLength; //碼長
string Codeword; //碼字
struct LinkList *Next; //下一結點
}LinkNode;
主函數:
void main() //主函數
{
LinkNode *L,*R,*S,*T; //定義鏈表節點
L=new LinkNode; //聲明
L->CodeLength=0;
L->Mark=L->Codeword=””;
L->P=L->SumP=0;
L->Next=NULL;
ifstream inf(“Data.txt”); //獲取數據
string s,temp;
int i=0; //標志作用
char InitialData[50]; //用于保存讀取出來的數字的數組
while (std::getline(inf, s)) //將inf文件中的數字讀取到data數組中
{
char *p;
if(i>1) //第二行開始
{
S=new LinkNode;
S->Next=NULL;
}
strcpy(InitialData,s.c_str());
p = strtok(InitialData, ” “);
while(p) //信原符號、概率、碼長
{
if(i>1&&i%2==0) //第一列
{
S->Mark=p;
}
if(i>1&&i%2==1) //第二列
{
temp=p;
S->P=(double)atof(temp.c_str());
if(S->P<0)
{
cout<
return;
}
S->CodeLength=int(-log(S->P)/log(2))+1;
}
p = strtok(NULL, ” “);
i++;
}
if(i>=4) //排序并算出累加概率
{
T=L->Next;
R=L;
while(T!=NULL)
{
T->SumP=R->SumP+R->P;
if(S->P>T->P&&S->Next==NULL)
{
R->Next=S;
S->Next=T;
S->SumP=R->SumP+R->P;
T->SumP=S->SumP+S->P;
}
R=T;
T=R->Next;
}
if(S->Next==NULL) //S概率最小的情況
{
R->Next=S;
S->SumP=R->P+R->SumP;
}
}
}
if((S->Next==NULL&&(S->P+S->SumP)!=1)||(R->Next==NULL&&(R->P+R->SumP)!=1)) //判斷概率格式
{
cout<
return;
}
R=L;
T=R->Next;
double Code;
cout<
while(T!=NULL) //得出碼字、輸出、銷毀鏈表
{
Code=T->SumP;
for(int j=1;j<=T->CodeLength;j++)
{
Code*=2;
if(Code<1)
{
T->Codeword+=”0″;
}
else
{
T->Codeword+=”1″;
Code=Code-int(Code);
}
}
cout<Mark<P<SumP<CodeLength<Codeword<
delete(R);
R=T;
T=T->Next;
}
delete(R);
delete(T);
inf.close(); //讀取完畢后,關閉文件
}
運行結果:
總結
以上是生活随笔為你收集整理的香农编码简单例题_单链表逆序输出c语言的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【推荐系统(一)】协同过滤之基于领域的方
- 下一篇: 【推荐系统(二)】协同过滤之隐语义模型(