我在用C#写一个huffman编码的窗体程序,但是在遍历huffman树的时候进入了死循环,我看了一下午没找到答案

问题描述

希望高手能够指点一下!谢了。。。

form1.csusingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Collections;namespaceAL_4{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privatestringstr;privatestringtext="";//ArrayListstat=newArrayList();//List<Huffman>huffman=newList<Huffman>();List<Huffman>stat=newList<Huffman>();privatevoidstatistic(stringstr){List<string>CharTemp=newList<string>();for(inti=0;i<str.Length;i++){if(CharTemp.Count==0){CharTemp.Add(str[i].ToString());continue;}intcount=0;for(intj=0;j<CharTemp.Count;j++){if(!str[i].ToString().Equals(CharTemp[j].ToString())){count++;}}if(count==CharTemp.Count){CharTemp.Add(str[i].ToString());}}for(inti=0;i<CharTemp.Count;i++){inttotal=0;for(intj=0;j<str.Length;j++){if(CharTemp[i].Equals(str[j].ToString())){total++;}}Huffmancs=newHuffman();cs.Char=CharTemp[i];cs.Times=total;stat.Add(cs);//textBox2.Text+=CharTemp[i]+"---->"+total.ToString()+"rn";}}voidcreatHuffman(){while(stat.Count>2){stat.Sort(sortAs_F);Huffmanh=newHuffman();Huffmanh1=newHuffman();Huffmanh2=newHuffman();h1=stat.First();stat.RemoveAt(0);h2=stat.First();stat.RemoveAt(0);h.Freq=h1.Freq+h2.Freq;h.Right=h1;h.Left=h2;h1.Parent=h;h2.Parent=h;h.Left.Code=0;h.Right.Code=1;stat.Add(h);}if(stat.Count==2){Huffmanh0=newHuffman();Huffmanh01=newHuffman();Huffmanh02=newHuffman();h01=stat.First();stat.RemoveAt(0);h02=stat.First();stat.RemoveAt(0);h0.Freq=h01.Freq+h02.Freq;h0.Right=h01;h0.Left=h02;h01.Parent=h0;h02.Parent=h0;h0.Left.Code=0;h0.Right.Code=1;stat.Add(h0);}}voidtraveHuffman(Huffmanh){while(h.Left!=null&&h.Right!=null){text=text+h.Code.ToString();traveHuffman(h.Left);traveHuffman(h.Right);}}privatevoidbutton1_Click(objectsender,EventArgse){str=textBox1.Text;statistic(str);//统计字符串中各字符出项的频率foreach(Huffmancinstat){c.Freq=(c.Times/str.Length);}//CompareClass_FmyCompare_F=newCompareClass_F();//stat.Sort(myCompare_F);//按字符的出现频率排序stat.Sort(sortAs_F);creatHuffman();//创建huffman树Huffmanh=newHuffman();h=stat.First();traveHuffman(h);//遍历huffman树textBox2.Text=text;}//排序//publicclassCompareClass_F:IComparer//{//intIComparer.Compare(objectx,objecty)//{//Huffmana=(Huffman)x;//Huffmanb=(Huffman)y;//if(a.Freq<b.Freq)return1;//elseif(a.Freq==b.Freq)return0;//elsereturn-1;//}//}//按字符出现的频率从小到大排序intsortAs_F(Huffmana,Huffmanb){double_temp=a.Freq-b.Freq;if(_temp<0)return1;elseif(_temp>0)return-1;elsereturn0;}}}Huffman.csusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceAL_4{classHuffman{privatedoubleh_freq;privatedoubleh_times=0;privatestringh_char;privateinth_code;//huffman编码privateHuffmanh_left=null;privateHuffmanh_right=null;privateHuffmanh_parent=null;publicHuffman(){}publicdoubleFreq{get{returnh_freq;}set{h_freq=value;}}publicdoubleTimes{get{returnh_times;}set{h_times=value;}}publicstringChar{get{returnh_char;}set{h_char=value;}}publicintCode{get{returnh_code;}set{h_code=value;}}publicHuffmanLeft{get{returnh_left;}set{h_left=value;}}publicHuffmanRight{get{returnh_right;}set{h_right=value;}}publicHuffmanParent{get{returnh_parent;}set{h_parent=value;}}}}

解决方案

解决方案二:
参考:#include<stdio.h>#include<string.h>#include<malloc.h>#include<stdlib.h>#include<conio.h>#defineNN10000#defineM2*NN-1#defineIN0#defineOUT1#defineMAX_INT32767#definePRINTLNprintf("nnnnnnnn");typedefstruct{intwi;charc;inttag;intparent,lchild,rchild;}huffmtype;typedefchar*encodetype[NN+1];typedefstruct{charc;inttimes;}codetype;voidPRINT(){PRINTLN;printf("tttHuffman编/译码器n");printf("ttt====================n");printf("ttt1.编码2.译码3.退出nn");printf("ttt>>选择:");}FILE*OpenFile(charfilename[20],chartype[3]){FILE*fp=NULL;if((fp=fopen(filename,type))==NULL)exit(1);returnfp;}intReadCode(codetype*code,FILE*fp){charc;//保存某次从文件中读入字符-intn=1;//记录首次出现字符在数组中的下标-inti;//循环变量-intcnt=1;inttag;//标志某次读入字符是否为首次出现字符,tag=1表示是首次出现;tag=0表示本次读入字符为已有字符while((c=fgetc(fp))!=EOF)//当文件没有结束时读入字符-{//从fp指向文件中读取字符,存入字符变量c中-tag=1;//假设本次读取字符为首次出现字符-for(i=1;i<n;i++){if(c==code[i].c)//如果本次读入字符为存储在下标为i已有字符-{code[i].times++;//权值加1-tag=0;//标记本字符为已有字符-break;//在已有数组元素中找到本次读入字符,结束for(;;)循环-}}if(tag)//当本字符为首次出现字符时-{code[n].c=c;//把改字符存入n指向的数组单元中-code[n].times=1;//记字符出现次数为1-n++;//n指向下一个数组地址-}}returnn-1;//返回文件中字符集合的元素个数-}voidInitHuffmanTree(huffmtype*huffmtree,intreal_n,intreal_m)//初始化-{inti;for(i=real_n;i<=real_m;i++){huffmtree[i].wi=0;huffmtree[i].c=0;huffmtree[i].tag=IN;huffmtree[i].lchild=huffmtree[i].rchild=huffmtree[i].parent=0;}}voidReadDataWeight_Init(huffmtype*huffmtree,codetype*code,intreal_n)//获取权值及数值域值-{inti;for(i=1;i<=real_n;i++)//-{huffmtree[i].wi=code[i].times;huffmtree[i].c=code[i].c;huffmtree[i].tag=IN;huffmtree[i].lchild=huffmtree[i].rchild=huffmtree[i].parent=0;}}intLeastNode(huffmtype*huffmtree,intmax_i)//找到最小权值节点地址-{inti;intleast_i;intmax=MAX_INT;for(i=1;i<=max_i;i++)//遍历1到max_i节点-{if(huffmtree[i].wi<max&&huffmtree[i].tag==IN)//若节点权值比max小并且在森林中-{max=huffmtree[i].wi;//刷新max值-least_i=i;//保存当前节点地址-}}huffmtree[least_i].tag=OUT;//将最小权值节点从森林中移除-returnleast_i;//返回最小节点地址}voidSlect(huffmtype*huffmtree,intmax_i,int*x1,int*x2)//找到权值最小的两个节点,并将其下标值保存在x1,x2中-{*x1=LeastNode(huffmtree,max_i);//计算合法最下权值下标-*x2=LeastNode(huffmtree,max_i);//}voidCreatHuffmanTree(huffmtype*huffmtree,intreal_n,intreal_m)//创建哈弗曼树-{inti;intx1,x2;for(i=real_n+1;i<=real_m;i++){Slect(huffmtree,i-1,&x1,&x2);//找到权值最小的两个节点,并将其下标值保存在x1,x2中-huffmtree[i].wi=huffmtree[x1].wi+huffmtree[x2].wi;//计算双气节点权值-huffmtree[x1].parent=huffmtree[x2].parent=i;//计算双亲节点地址-huffmtree[i].lchild=x1;huffmtree[i].rchild=x2;//计算双亲节点左右孩子地址-}}voidEncode(huffmtype*huffmtree,encodetypeencode,intreal_n)//依据已创建的HuffmanTree对字符进行编码-{char*cd;inti;intstart;intc,p;cd=(char*)malloc(real_n*sizeof(char));//cd用来存放某次运行时当前字符编码-cd[real_n-1]='';//作为字符结束符-for(i=1;i<=real_n;i++)//对real_n个节点进行遍历-{start=real_n-1;c=i;//c保存当前节点地址(下标)-p=huffmtree[i].parent;//p保存当前节点双亲地址-while(p){start--;//计算编码的起始地址-if(huffmtree[p].lchild==c)//若当前节点为其双亲的左孩子-{cd[start]='0';//编码为0-}else//若为右孩子-{cd[start]='1';//编码为1-}c=p;//节点前进-p=huffmtree[p].parent;//计算前进后节点双亲节点地址-}encode[i]=(char*)malloc((real_n-start)*sizeof(char));//申请空间用于存放编码-strcpy(encode[i],&cd[start]);//将本次编码存入encode数组中-}free(cd);//释放闲置存储空间-}voidWriteToFile(FILE*fp,encodetypeencode,codetype*code,intreal_n,char*readfile)//将编码输出到文件{inti;charcod[NN];FILE*fp2;charc;intcnt=1,j;fp2=fopen(readfile,"rt");while((c=fgetc(fp2))!=EOF){cod[cnt++]=c;}fclose(fp2);for(i=1;i<cnt;i++){for(j=1;j<=real_n;j++){if(cod[i]==code[j].c){break;}}fprintf(fp,"%s",encode[j]);}fclose(fp);}intIsError(FILE*fp)//对打开文件进行出错判断-{if(!fp){printf("ttt×打开文件错误n");printf("ttt任意键返回主菜单");getch();return1;//文件打开失败-}return0;//文件打开成功-}voidGetFilename(char*filename,chartype[13])//得到用户输入相关文件名{system("cls");PRINTLN;printf("ttt%s:",type);fflush(stdin);gets(filename);}intPutIntoCode(codetypecode[],huffmtypehuffmtree[])//编码函数{encodetypeencode;FILE*fp;//文件类型指针-intreal_n;//用来存放字符集长度-charreadfile[20];//从readfile文件中读取字符,写入到writefile文件中-GetFilename(readfile,"读取源文件");//从键盘读取文件名-fp=OpenFile(readfile,"rt");//打开待编码文件-if(IsError(fp))//判断是否正确打开文件-{return0;//打开文件失败,返回主菜单-}real_n=ReadCode(code,fp);//从readfile文件读取字符,将字符集合元素存入code数组,将集合元素个数存入real_n-fclose(fp);//关闭文件-ReadDataWeight_Init(huffmtree,code,real_n);//初始化HuffmanTree中从1到real_n的元素-InitHuffmanTree(huffmtree,real_n,2*real_n-1);//初始化HuffmanTree中real_n到2*real_n的元素-CreatHuffmanTree(huffmtree,real_n,2*real_n-1);//创建HuffmanTree-Encode(huffmtree,encode,real_n);//根据HuffmanTree对字符进行编码,编码结果保存到encode数组中-fp=OpenFile("CodeFile.txt","wb");//打开待写入文件-WriteToFile(fp,encode,code,real_n,readfile);//将encode数组中元素写入到文件中-fclose(fp);//关闭文件-printf("ttt完成编码并保存至CodeFile.txt文件中");//打印完成编码信息-getch();//等待用户输入任意键返回主菜单-returnreal_n;}voidTranslate(codetypecode[],huffmtypehuffmtree[],intreal_n)//译码函数{FILE*fp,*fp2;inti,real_m;charc;charwritefile[20];GetFilename(writefile,"保存解码文件到");fp=OpenFile("CodeFile.txt","rb");fp2=OpenFile(writefile,"wt");if(IsError(fp)){return;}i=real_m=2*real_n-1;while((c=fgetc(fp))!=EOF){if(c=='0'){i=huffmtree[i].lchild;}else{i=huffmtree[i].rchild;}if(huffmtree[i].lchild==0){fputc(code[i].c,fp2);i=real_m;}}fclose(fp);fclose(fp2);printf("ttt完成译码任务");getch();}intmain(void){intchoice;intreal_n=0;codetypecode[NN];huffmtypehuffmtree[NN];while(1){system("cls");PRINT();scanf("%d",&choice);switch(choice){case1:real_n=PutIntoCode(code,huffmtree);break;//编码函数case2:if(real_n)Translate(code,huffmtree,real_n);break;//译码函数case3:exit(1);//退出程序default:printf("ttt★无效输入");getch();break;}}return0;}
解决方案三:
新手路过,代码很多,看得不是很懂遍历树,一般用递归以下代码是遍历树的一个简单方法,只需将node改为根节点privatevoidwrite_tb_nodes(TreeNodenode){object[]record=newobject[3];record[0]=node.NodeID;//节点IDrecord[1]=node.NodeName;//节点record[2]=node.FatherNode.NodeID;//父节点IDtb_Nodes.LoadDataRow(record,false);//将以上三项写到DataTableif(node.SubNodes.Count>0)//如果节点的子节点数>0,递归调用此方法,{//将所有子节点的前述三项写到DataTableforeach(TreeNodenode_tempinnode.SubNodes){write_tb_nodes(node_temp);}}}

时间: 2024-09-20 06:10:06

我在用C#写一个huffman编码的窗体程序,但是在遍历huffman树的时候进入了死循环,我看了一下午没找到答案的相关文章

vc 如何创建服务-VC 开机自动启动。不用写注册表的方法。想写一个服务来启动这个程序。

问题描述 VC 开机自动启动.不用写注册表的方法.想写一个服务来启动这个程序. 有个EXE程序想要它开机自动启动.我不想用写注册表的方法启动.看能不能够写一个服务来启动这个程序.如果可以麻烦大家能够提供源码.谢谢!!!!! 解决方案 创建服务,CreateService()

windows-用MFC写一个window蓝牙通讯的程序需要用到哪些

问题描述 用MFC写一个window蓝牙通讯的程序需要用到哪些 在vs2013环境下用MFC写一个window蓝牙通讯的程序,需要哪些东西,要Windows SDK吗?vs 2013是否自带有 windows SDK? 解决方案 #include < Winsock2.h > #include < Ws2bth.h > #include < BluetoothAPIs.h > #pragma comment(lib, "ws2_32.lib") #p

ava 基础-如何使用JavaSEAPI写一个实现DOS命令的程序?

问题描述 如何使用JavaSEAPI写一个实现DOS命令的程序? javaseAPI可以写出能够控制系统开关机,之类的程序...

log4j-想写一个docx转html的程序但是控制台显示的是这样,并且在html的第一行有警告

问题描述 想写一个docx转html的程序但是控制台显示的是这样,并且在html的第一行有警告 log4j:WARN No appenders could be found for logger (org.docx4j.jaxb.Context). log4j:WARN Please initialize the log4j system properly. 解决方案 实际上这种警告很正常的,网上也有对应消除警告的方法:http://blog.sina.com.cn/s/blog_5f7d1a6

c语言-如何用C语言写一个暴力破解SSH的程序

问题描述 如何用C语言写一个暴力破解SSH的程序 也就是用同文件夹里的一个字典,可以用fopen和fgets把密码一条一条打开,可是我不知道怎么在C语言里对一个其他地址进行SSH 求大神解答 解决方案 C语言没有 SSH 的功能,所以需要你去自己搞 SSH 算法. 解决方案二: 参考openssh,这个是开源的,可以用它来调用,连接http://www.openssh.com/

C#写的一个串口通信的窗体程序,运行几个小时就出错,提示“操作已超时”或“已停止工作”,请问怎么解决

问题描述 C#写的一个串口通信的窗体程序,运行几个小时就出错,提示"操作已超时"或"已停止工作",请问怎么解决?求高手解答 解决方案 解决方案二:用日志记录出错信息以及出错的位置,然后再具体分析原因解决方案三:看下你做了一些什么操作解决方案四:就是直接打开串口接收数据,并将一些特定的语句写入文件.就这样运行一段时间就出错了.解决方案五:能贴代码吗关键是报什么错解决方案六: 解决方案七:麻烦帮忙看看怎么回事,谢谢了解决方案八:把有可能会抛异常的点,都放到trycatc

写一个用户在线显示的程序

在开始这篇文章时,作者假设读者已能够写出一个用户的登入认证程序. ---------------------------------------------------------- 记数器可完成访问 web 页的总次数,但却不能得知一个时段中访问量的动态记载,下面就来介绍如何写一个各个时段动态显示访问量的方法. 要记载访问量,首先就要在 mysql 内建立一个数据库,姑且给这个数据库取名为 line,同时建立一个名为 line 的数据表,表内的字段分别为"用户名(name varchar(20

php 进阶:写一个用户在线显示的程序

在开始这篇文章时,作者假设读者已能够写出一个用户的登入认证程序. ---------------------------------------------------------- 记数器可完成访问 web 页的总次数,但却不能得知一个时段中访问量的动态记载,下面就来介绍如何写一个各个时段动态显示访问量的方法. 要记载访问量,首先就要在 mysql 内建立一个数据库,姑且给这个数据库取名为 line,同时建立一个名为 line 的数据表,表内的字段分别为"用户名(name varchar(20

用ASP.Net写一个发送ICQ信息的程序代码

asp.net|程序 这里我给大家提供一个很实用的例子,就是在线发送ICQ信息.想一想我们在网页上直接给朋友发送ICQ信息,那是多么美妙的事情啊.呵呵,在吹牛啊,其实ICQ本来就有在线发送的代码,不过,这些都是AOL给你写好的代码,多没有意思啊.还是自已写的比较好,呵呵,废话少说,大家来看代码吧. <% @ Page Language="C#" %><% @ Assembly Name="System.Net" %><% @ Impor