数据结构实习Huffman编译码器(二)

实现思想:

1.首先分析输入的报文,得到各个字符出现的次数和概率,将出现次数作为权重构建哈夫曼树

2.构造huffman树,并动态显示Huffman树的生成过程

3,对每个字符进行编码

4.对字符串编译码

5,Socket编程实现通信(重点学习)

界面:




关键代码:

1.

 enum { IDD = IDD_HUFFMAN_DIALOG };
 CListCtrl m_plist;
 CString m_mes;


 

——————————————————

m_plist.InsertColumn( 0, "字符", LVCFMT_LEFT, 40 );//插入列
 m_plist.InsertColumn( 1, "次数", LVCFMT_CENTER, 40 );//插入列
 m_plist.InsertColumn( 2, "概率", LVCFMT_CENTER, 60 );//插入列
 m_plist.InsertColumn( 3, "hfm编码", LVCFMT_CENTER, 100 );//插入列


 

————————————————————

int CHuffmanDlg::Probability(CString str)//统计每个字符出现概率,返回不同字符个数
{
 CString pro;//存储字符概率
 if (str==""){MessageBox("输入报文为空!"); return 0;}
 int StrLength=str.GetLength();//字符串总长
 int i=0,j=0;
 CString temp;
 while (str!="")
 { 
  temp.Format(_T("%c"), str[0]);;
  m_plist.InsertItem(i,temp);//字符
  j=str.Remove(str[0]);
  temp.Format(_T("%d"),j);//字符出现次数
  m_plist.SetItemText(i,1,temp);
  temp.Format(_T("%3f"),(double)j/StrLength);
  m_plist.SetItemText(i,2,temp);//字符出现概率
  i++;
 }
 return i;


2.huffman树和节点的数据结构定义

typedef struct HuffmanNode                                             
{
	int weight;//权值
	char character;//存放字符
	bool isLeaf;//是否叶子节点
	int createSort;   //用于标记节点创建顺序
	int position;   //用于记录节点在树中的位置。以完全二叉树计算的
	HuffmanNode *leftChild,*rightChild,*parent;//三叉链表指针
	HuffmanNode():leftChild(NULL),rightChild(NULL),parent(NULL){}
	HuffmanNode(int elem,char ch,HuffmanNode* left = NULL, HuffmanNode* right = NULL, HuffmanNode* ptr = NULL ):weight(elem),character(ch),
		leftChild(left), rightChild(right), parent(ptr){}
	bool operator <=(HuffmanNode& R){return weight <= R.weight;}
	bool operator > (HuffmanNode& R){return weight > R.weight;}
	HuffmanNode* sAddress;
	int visited;//访问标记,编码时使用
	CString hfmCode;
}HuffmanNode;

class HuffanTree  
{
public:
	int createSort;
	void mergeTree(HuffmanNode & ht1, HuffmanNode & ht2, HuffmanNode*& parent);
	void enCode(int n,CListCtrl *list);   //对哈弗曼树进行编码  ,n个叶子节点
	void CreateHfmTree(int n,CListCtrl * list);//创建哈弗曼树
	HuffanTree();
	virtual ~HuffanTree();
	
	HuffmanNode *huffNode[256];  //申请编码空间,最多有256中不同字符
	HuffmanNode* root;
	int codeTotal;     //编码节点的个数,即需要多少个huffmanNode
	HuffmanNode* rootFull;   //绘画时候需要的满二叉树
};

创建huffman树:

void HuffanTree::CreateHfmTree(int n,CListCtrl *list)
{
	codeTotal = n;    //总共需要n个节点,因为共出现了n个不重复的字符
	createSort=1;
	int i,elem;//elem为字符出现次数,置为权值
	char ch;//字符
	MinHeap hp(n);//初始化最小堆
	CString str;
	HuffmanNode *parent,first,second,*work;
	
	for (i=0;i<codeTotal;i++)//构造n个叶子节点
	{
		elem=_ttoi(list->GetItemText(i,1));//CString转为int
		ch= list->GetItemText(i,0)[0];
		work = new HuffmanNode;
		work->weight = elem;
		work->character = ch;
		work->position = i;
		work->isLeaf = true;
		work->visited=0;//叶子节点记录为未访问
		work->leftChild = NULL;
		work->rightChild = NULL;
		work->parent = NULL;
		work->sAddress = work;
		hp.Insert(*work);
		//huffNode[i]=work;
	}
	int leafNum=0;
	for(i = 0; i < n-1; i++){
		
		hp.RemoveMin(first);

		hp.RemoveMin(second);
		mergeTree(first,second,parent);
		if (first.rightChild==NULL&&first.leftChild==NULL)
		{
			huffNode[leafNum++]=first.sAddress;
		}
		if (second.rightChild==NULL&&second.leftChild==NULL)//记录叶子节点
		{
			huffNode[leafNum++]=second.sAddress;
		}
		hp.Insert(*parent);
	}
	root = parent;
    
	root->createSort = createSort;//最后创建
}


 

void HuffanTree::mergeTree(HuffmanNode &ht1, HuffmanNode  &ht2, HuffmanNode* & parent)
{
	parent = new HuffmanNode;
	parent->leftChild = ht1.sAddress;
	parent->rightChild = ht2.sAddress;
	parent->weight = ht1.weight + ht2.weight;
	parent->position = -1;         //给父节点的位置赋-1,父节点不是要编码的节点
	parent->character = '#';       //给父节点一个标志
	parent->visited=1;              //父节点标记为已访问
	ht1.sAddress->parent = ht2.sAddress->parent = parent;
	ht1.sAddress->createSort = createSort++;
	ht2.sAddress->createSort = createSort++;
	parent->isLeaf = false;
	parent->sAddress=parent;
}



 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值