pam編解碼實驗問題
A. 哈夫曼編/解碼器問題:C語言版的數據結構,我急啊!那位朋友幫幫忙,結果必需是我的問題的結果,不能有錯啊
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//////////////////////////////////////////////////////////////////////////////
/*定義赫夫曼樹結點的結構體變數,存放結點的權值、字元、雙親、坐孩子和右孩子*/
typedef struct{
int weight;
char ch; //增加一個域用於存放該節點的字元
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode; //指向赫夫曼編碼的指針
//////////////////////////////////////////////////////////////////////////////
/*本程序用到的函數原型*/
void welcome(); //列印操作選擇界面
void HuffmanCoding(HuffmanTree &,char *,int *,int);//建立赫夫曼樹的演算法
void select(HuffmanTree HT,int j,int *s1,int *s2); //從目前已建好的赫夫曼樹中選擇parent為0且weight最小的兩個結點
void Init(); //輸入n個字元及其對應的權值,根據權值建立哈夫曼樹
void Coding(); //編碼
void Decoding(); //解碼
void Print_code(); //列印解碼好的代碼文件
void Print_tree(); //以凹凸表形式列印哈夫曼樹
int Read_tree(HuffmanTree &); //從文件中讀入赫夫曼樹
void find(HuffmanTree &HT,char *code,char *text,int i,int m);//解碼時根據01字元串尋找相應葉子節點的遞歸演算法
void Convert_tree(unsigned char T[100][100],int s,int *i,int j);//將內存中的赫夫曼樹轉換成凹凸表形式的赫夫曼樹
HuffmanTree HT; //全局變數,指向存放赫夫曼樹的存儲空間
int n=0; //全局變數,存放赫夫曼樹葉子結點的數目
int main()
{
char select;
while(1)
{
welcome();
scanf("%c",&select);
switch(select)
{
case 'i':
case 'I':Init();break;
case 'c':
case 'C':Coding();break;
case 'd':
case 'D':Decoding();break;
case 'p':
case 'P':Print_code();break;
case 't':
case 'T':Print_tree();break;
case 'e':
case 'E':exit(1);
default :printf("Input error!\n");
}
getchar();
}
return 0;
}
void welcome() //列印操作選擇界面
{
printf("*-----------------------------------------------------*\n");
printf("| What do you want to do? |\n");
printf("|-----------------------------------------------------|\n");
printf("| |\n");
printf("| I--------------------------Init the Huffman tree. |\n");
printf("| C--------------------------Code your file. |\n");
printf("| D--------------------------Decode the code. |\n");
printf("| P--------------------------Print the codefile. |\n");
printf("| T--------------------------Print the Huffman tree. |\n");
printf("| |\n");
printf("*-----------------------------------------------------*\n");
}
//////////////////////////////////////////////////////////////////////////////////////
/*初始化函數,輸入n個字元及其對應的權值,根據權值建立哈夫曼樹,並將其存於文件hfmtree中*/
void Init()
{
FILE *fp;
int i,n,w[52]; //w數組存放n個字元的權值
char character[52]; //存放n個字元
printf("\n輸入字元個數 n:");
scanf("%d",&n); //輸入字元集大小
printf("輸入%d個字元及其對應的權值:\n",n);
for (i=0;i<n;i++)
{
char b=getchar();
scanf("%c",&character[i]);
scanf("%d",&w[i]); //輸入n個字元和對應的權值
}
HuffmanCoding(HT,character,w,n); //建立赫夫曼樹
if((fp=fopen("hfmtree.txt","w"))==NULL)
printf("Open file hfmtree.txt error!\n");
for (i=1;i<=2*n-1;i++)
{
if(fwrite(&HT[i],sizeof(HTNode),1,fp)!=1) //將建立的赫夫曼樹存入文件hfmtree.txt中
printf("File write error!\n");
}
printf("\n建立赫夫曼樹成功,已將其存於文件hfmtree.txt中\n");
fclose(fp);
}
///////////////////////////////////////////////////////////////////////////////////
//////建立赫夫曼樹的演算法///////////////////////////////////////////////////////////
void HuffmanCoding(HuffmanTree &HT,char *character,int *w,int n)
{
int m,i,s1,s2;
HuffmanTree p;
if(n<=1) return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT+1,i=1;i<=n;++i,++p,++character,++w)
{p->ch=*character;p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;}
for(;i<=m;++i,++p) {p->ch=0;p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;}
for(i=n+1;i<=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;
}
}
///////////////////////////////////////////////////////////////////////////////
/*從HT[1]到HT[j]中選擇parent為0且weight最小的兩個結點,用s1和s2返回其序號*/
void select(HuffmanTree HT,int j,int *s1,int *s2)
{
int i;
//找weight最小的結點
for (i=1;i<=j;i++)
if (HT[i].parent==0)
{*s1=i;break;}
for (;i<=j;i++)
if ((HT[i].parent==0)&&(HT[i].weight<HT[*s1].weight))
*s1=i;
HT[*s1].parent=1;
//找weight次小的結點
for (i=1;i<=j;i++)
if (HT[i].parent==0)
{*s2=i;break;}
for (;i<=j;i++)
if ((HT[i].parent==0)&&(i!=*s1)&&(HT[i].weight<HT[*s2].weight))
*s2=i;
}
///////////////////////////////////////////////////////////////////////////////
/*對文件tobetrans中的正文進行編碼,然後將結果存入文件codefile中*/
void Coding()
{
FILE *fp,*fw;
int i,f,c,start;
char *cd;
HuffmanCode HC;
if(n==0)
n=Read_tree(HT);//從文件hfmtree.txt中讀入赫夫曼樹,返回葉子結點數
/////以下程序段求赫夫曼樹中各葉子節點的字元對應的的編碼,並存於HC指向的空間中
{
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
start=n-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
if(HT[f].lchild==c)
cd[--start]='0';
else cd[--start]='1';
HC[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
/////////////////////////////////////////////////////////////////////////////////////
if((fp=fopen("tobetrans.txt","rb"))==NULL)
printf("Open file tobetrans.txt error!\n");
if((fw=fopen("codefile.txt","wb+"))==NULL)
printf("Open file codefile.txt error!\n");
char temp;
fscanf(fp,"%c",&temp); //從文件讀入第一個字元
while(!feof(fp))
{
for(i=1;i<=n;i++)
if(HT[i].ch==temp) break; //在赫夫曼樹中查找字元所在的位置
for(int r=0;HC[i][r]!='\0';r++) //將字元對應的編碼存入文件
fputc(HC[i][r],fw);
fscanf(fp,"%c",&temp); //從文件讀入下一個字元
}
fclose(fw);
fclose(fp);
printf("\n對文件hfmtree.txt編碼成功,結果已存入codefile.txt中。\n\n");
}
/////////////////////////////////////////////////////////////////////////
/*將文件codefile中的代碼進行解碼,結果存入文件textfile中*/
void Decoding()
{
FILE *fp,*fw;
int m,i;
char *code,*text,*p;
if(n==0)
n=Read_tree(HT);//從文件hfmtree.txt中讀入赫夫曼樹,返回葉子結點數
if((fp=fopen("codefile.txt","rb"))==NULL)
printf("Open file codefile.txt error!\n");
if((fw=fopen("textfile.txt","wb+"))==NULL)
printf("Open file textfile.txt error!\n");
code=(char *)malloc(sizeof(char));
fscanf(fp,"%c",code); //從文件讀入一個字元
for(i=1;!feof(fp);i++)
{
code=(char *)realloc(code,(i+1)*sizeof(char)); //增加空間
fscanf(fp,"%c",&code[i]); //從文件讀入下一個字元
}
code[i-1]='\0';
/////////到此codefile.txt文件中的字元已全部讀入,存放在code數組中
text=(char *)malloc(100*sizeof(char));
p=text;
m=2*n-1;
if(*code=='0')
find(HT,code,text,HT[m].lchild,m); //從根節點的左子樹去找
else
find(HT,code,text,HT[m].rchild,m); //從根節點的右子樹去找
for(i=0;p[i]!='\0';i++) //把解碼好的字元存入文件textfile.txt中
fputc(p[i],fw);
fclose(fp);
fclose(fw);
printf("\n對codefile.txt文件解碼成功,結果已存入textfile.txt文件。\n\n");
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
/*將文件codefi1e以緊湊格式顯示在終端上,每行50個代碼。同時將此字元形式的編碼文件寫入文件codeprint中。*/
void Print_code()
{
FILE *fp,*fw;
char temp;
int i;
if((fp=fopen("codefile.txt","rb"))==NULL)
printf("Open file codefile.txt error!\n");
if((fw=fopen("codeprint.txt","wb+"))==NULL)
printf("Open file codeprint.txt error!\n");
printf("\n文件codefi1e以緊湊格式顯示如下:\n");
fscanf(fp,"%c",&temp); //從文件讀入一個字元
for (i=1;!feof(fp);i++)
{
printf("%c",temp);
if(i%50==0) printf("\n");
fputc(temp,fw); //將該字元存入文件codeprint.txt中
fscanf(fp,"%c",&temp); //從文件讀入一個字元
}
printf("\n\n此字元形式的編碼已寫入文件codeprint.txt中.\n\n");
fclose(fp);
fclose(fw);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/*將已在內存中的哈夫曼樹以凹凸表形式顯示在屏幕上,同時將此字元形式的哈夫曼樹寫入文件treeprint中。*/
void Print_tree()
{
unsigned char T[100][100];
int i,j,m=0;
FILE *fp;
if(n==0)
n=Read_tree(HT);//從文件hfmtree.txt中讀入赫夫曼樹,返回葉子結點數
Convert_tree(T,0,&m,2*n-1); //將內存中的赫夫曼樹轉換成凹凸表形式的樹,存於數組T中
if((fp=fopen("treeprint.txt","wb+"))==NULL)
printf("Open file treeprint.txt error!\n");
printf("\n以凹凸表形式列印已建好的赫夫曼樹:\n");
for(i=1;i<=2*n-1;i++)
{
for (j=0;T[i][j]!=0;j++)
{
if(T[i][j]==' ') {printf(" ");fputc(T[i][j],fp);}
else
{printf("%d",T[i][j]);fprintf(fp,"%d\n",T[i][j]);}
}
printf("\n");
}
fclose(fp);
printf("\n此字元形式的哈夫曼樹已寫入文件treeprint.txt中.\n\n");
}
//////////////////////////////////////////////////////////////////////////////////
/*從文件hfmtree.txt中讀入赫夫曼樹,返回葉子節點數*/
int Read_tree(HuffmanTree &HT)
{
FILE *fp;
int i,n;
HT=(HuffmanTree)malloc(sizeof(HTNode));
if((fp=fopen("hfmtree.txt","r"))==NULL)
printf("Open file hfmtree.txt error!\n");
for (i=1;!feof(fp);i++)
{
HT=(HuffmanTree)realloc(HT,(i+1)*sizeof(HTNode)); //增加空間
fread(&HT[i],sizeof(HTNode),1,fp); //讀入一個節點信息
}
fclose(fp);
n=(i-1)/2;
return n;
}
////////////////////////////////////////////////////////////////
/*解碼時根據01字元串尋找相應葉子節點的遞歸演算法*/
void find(HuffmanTree &HT,char *code,char *text,int i,int m)
{
if(*code!='\0') //若解碼未結束
{
code++;
if(HT[i].lchild==0&&HT[i].rchild==0) //若找到葉子節點
{
*text=HT[i].ch; //將葉子節點的字元存入text中
text++;
if((*code=='0'))
find(HT,code,text,HT[m].lchild,m); //繼續從根節點的左子樹找
else
find(HT,code,text,HT[m].rchild,m); //繼續從根節點的右子樹找
}
else //如果不是葉子節點
if(*code=='0')
find(HT,code,text,HT[i].lchild,m); //從該節點的左子樹去找
else
find(HT,code,text,HT[i].rchild,m); //從該節點的右子樹去找
}
else
*text='\0'; //解碼結束
}
////////////////////////////////////////////////////////////////////////
/*將內存中的赫夫曼樹轉換成凹凸表形式的赫夫曼樹*/
void Convert_tree(unsigned char T[100][100],int s,int *i,int j)
{
int k,l;
l=++(*i);
for(k=0;k<s;k++)
T[l][k]=' ';
T[l][k]=HT[j].weight;
if(HT[j].lchild)
Convert_tree(T,s+1,i,HT[j].lchild);
if(HT[j].rchild)
Convert_tree(T,s+1,i,HT[j].rchild);
T[l][++k]='\0';
}
為了您的安全,請只打開來源可靠的網址
打開網站 取消
來自: http://hi..com/laij/blog/item/4f3edefb6008321e6c22eb34.html
B. 關於AMI、HDB3編譯碼實驗 有個這樣的思考題,示波器看到的HDB3變換規則與書本上和老師講的有什麼不同
示波器上看到的HDB3編碼器的輸出P22點的波形比書本上的理論上的輸出波形要延時5個碼位。原因是實驗電路中採用了由4個移位寄存器和與非門組成的四連零測試模塊去檢測二進制碼流中是否有四連零,因此輸出的HDB3碼有5個碼位的延時。