//哈夫曼编码/
/* //maxnode = 2*n-1
哈夫曼编码:从队列中取出权重最小的两个节点,进行构造树
将新生成的节点作为父节点
使用结构体:
Node(node1,node2,weight) //权重边信息保存
HuffmanTree(weight,family,lchild,rchild) //存储哈夫曼树
HTQueue(ht[],front,rear) //队列处理生成哈夫曼树
函数说明:
CreatHT (HuffmanTree ht,Node node[]) //在队列中构造哈夫曼树
输入:Node node[] //权重信息
int e //权重边数
输出:返回构造的哈夫曼树
函数简析:
初始化队列
while rear != front //队列不空
if front-rear == 1 return //只有一个元素
else get the 2 min-weight to deal() //取出权重最小的两个节点进行处理
deal (HTQueue &qt,int min1,int min2) //处理队列中的哈夫曼数节点排序情况
输入: HTQueue &qt //当前待处理队列的引用
int min1,int min2 //当前队列中权重最小的两个节点
输出:重新排序的队列
*/
#include <stdio.h>
#include <iostream>
#define MAXN 10 //叶子节点最大数
#include <iostream>
#define MAXN 10 //叶子节点最大数
typedef struct
{
int node1; //节点1
int node2; //节点2
int weight; //权重
}Node; //保存节点间路径
{
int node1; //节点1
int node2; //节点2
int weight; //权重
}Node; //保存节点间路径
typedef struct HMTree
{
Node node; //权重边信息
int family; //父节点
int lchild; //左孩子
int rchild; //右孩子
}HuffmanTree; //哈夫曼树树形存储
{
Node node; //权重边信息
int family; //父节点
int lchild; //左孩子
int rchild; //右孩子
}HuffmanTree; //哈夫曼树树形存储
typedef struct
{
HuffmanTree ht[2*MAXN-1]; //待处理队列
int front,rear; //队首,队尾
} HTQueue; //处理队列
{
HuffmanTree ht[2*MAXN-1]; //待处理队列
int front,rear; //队首,队尾
} HTQueue; //处理队列
void getNode (Node node[],int e);
void disp (HTQueue t,int start);
//哈夫曼编码/
HTQueue CreatHT (Node node[],int e);
void deal (HTQueue &qt,int min1,int min2);
///
void disp (HTQueue t,int start);
//哈夫曼编码/
HTQueue CreatHT (Node node[],int e);
void deal (HTQueue &qt,int min1,int min2);
///
int main ()
{
{
//输入样例
//5 10 0 0 0 0 1 8 0 3 5 1 1 0 1 2 3 2 2 0 2 4 6 3 1 9 3 3 0 4 4 0
/*
6 10
0 1 6
0 2 1
0 3 5
1 4 3
1 2 5
2 3 5
2 5 4
2 4 6
3 5 2
4 5 6
*/
int n,e;
printf ("请输入顶点数和边数:");
scanf ("%d %d",&n,&e);
Node node[e];
HTQueue ht;
getNode (node,e);
printf ("\n");
ht = CreatHT (node,e);
printf ("生成的哈夫曼树为:");
disp (ht,ht.front-1);
printf ("\n");
return 0;
}
//5 10 0 0 0 0 1 8 0 3 5 1 1 0 1 2 3 2 2 0 2 4 6 3 1 9 3 3 0 4 4 0
/*
6 10
0 1 6
0 2 1
0 3 5
1 4 3
1 2 5
2 3 5
2 5 4
2 4 6
3 5 2
4 5 6
*/
int n,e;
printf ("请输入顶点数和边数:");
scanf ("%d %d",&n,&e);
Node node[e];
HTQueue ht;
getNode (node,e);
printf ("\n");
ht = CreatHT (node,e);
printf ("生成的哈夫曼树为:");
disp (ht,ht.front-1);
printf ("\n");
return 0;
}
void getNode (Node node[],int e)
{
int i;
for (i=0; i<e; i++)
{
printf ("请输入第%d组连接顶点x,y与权重w:",i+1);
scanf ("%d %d %d",&node[i].node1,&node[i].node2,&node[i].weight);
}
}
{
int i;
for (i=0; i<e; i++)
{
printf ("请输入第%d组连接顶点x,y与权重w:",i+1);
scanf ("%d %d %d",&node[i].node1,&node[i].node2,&node[i].weight);
}
}
void disp (HTQueue t,int start)
{
printf ("%d",t.ht[start].node.weight);
if (t.ht[start].lchild!=-1 && t.ht[start].rchild!=-1)
{
printf ("(");
disp (t,t.ht[start].lchild);
printf (",");
disp (t,t.ht[start].rchild);
printf (")");
}
}
{
printf ("%d",t.ht[start].node.weight);
if (t.ht[start].lchild!=-1 && t.ht[start].rchild!=-1)
{
printf ("(");
disp (t,t.ht[start].lchild);
printf (",");
disp (t,t.ht[start].rchild);
printf (")");
}
}
void deal (HTQueue &qt,int min1,int min2)
{
HuffmanTree ht;
//初始化新节点权重值
qt.ht[qt.front].node.weight = qt.ht[min1].node.weight + qt.ht[min2].node.weight;
//将权重最小的两个节点放到当前处理队列最前面,并完善父子关系
if (qt.rear==min1) //如果权重最小的节点中较大的在当前处理队列的第一位
{ //eg:2 3 1转化为1 2 3。 ht=3; 3=2; 2=1; 1=ht (1 2 3表示位置)
ht = qt.ht[qt.rear+1]; //记录第二位
qt.ht[qt.rear+1] = qt.ht[qt.rear]; //将第二位换为第一位min1
qt.ht[qt.rear] = qt.ht[min2];//将第一位换为 min2节点
qt.ht[min2] = ht; //将记录的位放入原min2位置
}
else
{ //eg:3 4 1 2转化为1 2 3 4。ht=2; 2=3; 3=1; 1=4; 4=ht (1 2 3 4表示位置)
ht = qt.ht[min1];
qt.ht[min1]= qt.ht[qt.rear];
qt.ht[qt.rear] = qt.ht[min2];
qt.ht[min2] = qt.ht[qt.rear+1];
qt.ht[qt.rear+1] = ht;
}
qt.ht[qt.front].rchild = qt.rear; //将交换后的队首节点作为队尾节点的左孩子
qt.ht[qt.front].lchild = qt.rear+1;
qt.ht[qt.rear].family = qt.front; //将队尾节点作为交换后的队首节点的父亲
qt.ht[qt.rear+1].family = qt.front;
qt.rear += 2; //队首后移
qt.front++;
}
{
HuffmanTree ht;
//初始化新节点权重值
qt.ht[qt.front].node.weight = qt.ht[min1].node.weight + qt.ht[min2].node.weight;
//将权重最小的两个节点放到当前处理队列最前面,并完善父子关系
if (qt.rear==min1) //如果权重最小的节点中较大的在当前处理队列的第一位
{ //eg:2 3 1转化为1 2 3。 ht=3; 3=2; 2=1; 1=ht (1 2 3表示位置)
ht = qt.ht[qt.rear+1]; //记录第二位
qt.ht[qt.rear+1] = qt.ht[qt.rear]; //将第二位换为第一位min1
qt.ht[qt.rear] = qt.ht[min2];//将第一位换为 min2节点
qt.ht[min2] = ht; //将记录的位放入原min2位置
}
else
{ //eg:3 4 1 2转化为1 2 3 4。ht=2; 2=3; 3=1; 1=4; 4=ht (1 2 3 4表示位置)
ht = qt.ht[min1];
qt.ht[min1]= qt.ht[qt.rear];
qt.ht[qt.rear] = qt.ht[min2];
qt.ht[min2] = qt.ht[qt.rear+1];
qt.ht[qt.rear+1] = ht;
}
qt.ht[qt.front].rchild = qt.rear; //将交换后的队首节点作为队尾节点的左孩子
qt.ht[qt.front].lchild = qt.rear+1;
qt.ht[qt.rear].family = qt.front; //将队尾节点作为交换后的队首节点的父亲
qt.ht[qt.rear+1].family = qt.front;
qt.rear += 2; //队首后移
qt.front++;
}
HTQueue CreatHT (Node node[],int e)
{
HTQueue qt;
qt.front = qt.rear = 0;
int i,j,min1,min2,min3;
for (i=0; i<e; i++) //初始化队列,将所有节点进队,叶子节点子节点值置-1
{
qt.ht[qt.front].node = node[i];
qt.ht[qt.front].lchild = qt.ht[qt.front].rchild = -1;
qt.front ++;
}
while (qt.front != qt.rear)//当队列不空
{
if (qt.front-qt.rear == 1) //当只剩下一个元素
return qt;
else //找出队列里两个权重最小的节点并进行处理
{
min1 = qt.rear; min2 = qt.rear+1; //记录取出节点所在的队列位置
if (qt.ht[min1].node.weight<=qt.ht[min2].node.weight)
{
min3 = min1; min1 = min2; min2 = min3; //将权重较大的节点队列编号放在min1
}
for (j=qt.rear+2; j<qt.front; j++) //对未排序的队列进行查找两个最小的节点
{
if (qt.ht[j].node.weight<qt.ht[min1].node.weight) //当节点权重小于节点min1的权重
min1 = j;
if (qt.ht[min1].node.weight<=qt.ht[min2].node.weight)
{
min3 = min1; min1 = min2; min2 = min3; //将权重较大的节点队列编号放在min1
}
}
deal (qt,min1,min2); //调用处理函数将队列重新排序
}
}
}
{
HTQueue qt;
qt.front = qt.rear = 0;
int i,j,min1,min2,min3;
for (i=0; i<e; i++) //初始化队列,将所有节点进队,叶子节点子节点值置-1
{
qt.ht[qt.front].node = node[i];
qt.ht[qt.front].lchild = qt.ht[qt.front].rchild = -1;
qt.front ++;
}
while (qt.front != qt.rear)//当队列不空
{
if (qt.front-qt.rear == 1) //当只剩下一个元素
return qt;
else //找出队列里两个权重最小的节点并进行处理
{
min1 = qt.rear; min2 = qt.rear+1; //记录取出节点所在的队列位置
if (qt.ht[min1].node.weight<=qt.ht[min2].node.weight)
{
min3 = min1; min1 = min2; min2 = min3; //将权重较大的节点队列编号放在min1
}
for (j=qt.rear+2; j<qt.front; j++) //对未排序的队列进行查找两个最小的节点
{
if (qt.ht[j].node.weight<qt.ht[min1].node.weight) //当节点权重小于节点min1的权重
min1 = j;
if (qt.ht[min1].node.weight<=qt.ht[min2].node.weight)
{
min3 = min1; min1 = min2; min2 = min3; //将权重较大的节点队列编号放在min1
}
}
deal (qt,min1,min2); //调用处理函数将队列重新排序
}
}
}