目录
1811 求二叉树最小值_二叉树求最小值_a little funny的博客-CSDN博客
1809 三色二叉树 (7条消息) 洛谷P2585&ZJOI 2006-三色二叉树(树的染色-树形DP)_lonely_wind_的博客-CSDN博客
1802 (7条消息) 动态规划求树的最大连通分支问题_. 输入含有 n 个顶点的加权二叉树 t 和正数 τ,树 t 上每条边的权值都非负,树中顶_hnu哈哈的博客-CSDN博客
1821 判断完全二叉树(顺序存储)_牛客博客 (nowcoder.net)
1801 B - 树与二叉树_b树和二叉树_米诺minoz的博客-CSDN博客
1820 C 加分二叉树 - DWVictor - 博客园 (cnblogs.com)
1811 求二叉树最小值_二叉树求最小值_a little funny的博客-CSDN博客
C++版本的(DFS)
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
#define MAXN 100100
#define Min(a,b) ((a)<(b)?(a):(b))
struct Graph {
int vex, next;
} G[MAXN << 1]; //边存了两遍。
int first[MAXN], mn, md;
bool flag[MAXN];
void DFS(int pos, int dep) {
int tot; flag[pos] = true;
if (dep >= md) {
if (dep > md) {md = dep; mn = pos;}
else if (pos < mn) mn = pos;}
for (tot = first[pos]; tot != -1; tot = G[tot].next)
if (!flag[G[tot].vex]) DFS(G[tot].vex, dep + 1);}
int main() {
int n, i, tot, s, e, a;
while (scanf("%d", &n) != EOF) {
memset(first, -1, sizeof(first));
tot = 0;
for (i = 1; i < n; i++) {
scanf("%d %d", &s, &e);
G[tot].vex = e;
G[tot].next = first[s];
first[s] = tot++;
G[tot].vex = s;
G[tot].next = first[e];
first[e] = tot++;
}
memset(flag, false, sizeof(flag));
mn = md = -1;
DFS(1, 0);
a = mn;
memset(flag, false, sizeof(flag));
mn = md = -1;
DFS(a, 0);
printf("%d %d\n", Min(a,mn), md + 1);
}}
1809 三色二叉树 (7条消息) 洛谷P2585&ZJOI 2006-三色二叉树(树的染色-树形DP)_lonely_wind_的博客-CSDN博客
#include <bits/stdc++.h>
using namespace std;
#define debug printf("#@$@%\n")
const int mac=5e5+10;
char s[mac];
vector<int>g[mac];
int cnt=0,dp[mac][3];
int dp2[mac][3];
int dfs_wedge(char *s,int fa)
{
if (!s[0]) return 0;
int nb=1;
cnt++;
if (fa!=-1){
g[cnt].push_back(fa);
g[fa].push_back(cnt);
}
if (s[0]=='0') return nb;
int u=cnt;
nb+=dfs_wedge(s+1,u);
if (s[0]=='2') nb+=dfs_wedge(s+nb,u);
return nb;
}
void dfs(int u,int fa)
{
int v1=0,v2=0;
for (int i=0; i<g[u].size(); i++){
int v=g[u][i];
if (v==fa) continue;
dfs(v,u);
dp[u][1]+=dp[v][0];
dp2[u][1]+=dp2[v][0];
if (v1) v2=v;
else v1=v;
}
dp[u][1]++; dp2[u][1]++;
if (v2) {
dp2[u][0]=min(dp2[v1][1]+dp2[v2][0],dp2[v1][0]+dp2[v2][1]);
dp[u][0]=max(dp[v1][0]+dp[v2][0],max(dp[v1][0]+dp[v2][1],dp[v1][1]+dp[v2][0]));
}
else if (v1) dp[u][0]=max(dp[v1][0],dp[v1][1]),dp2[u][0]=min(dp2[v1][0],dp2[v1][1]);
}
int main(int argc, char const *argv[])
{
scanf ("%s",s+1);
if (s[1]=='0') {printf("%d %d\n",1,0); return 0;}
dfs_wedge(s+1,-1);
int n=strlen(s+1);
dfs(1,-1);
printf("%d %d\n",max(dp[1][0],dp[1][1]),min(dp2[1][0],dp2[1][1]));
return 0;
}
1802 (7条消息) 动态规划求树的最大连通分支问题_. 输入含有 n 个顶点的加权二叉树 t 和正数 τ,树 t 上每条边的权值都非负,树中顶_hnu哈哈的博客-CSDN博客
谢谢,已经被折磨到不想再用标准C写东西了。手写图 链表 树是什么人间疾苦,
既然还要学ACM 为什么数据结构不直接教C++呢
#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <stack>
using namespace std;
struct node {int w, parent, level, visit;
node() {w=parent=level=visit=0;}};
vector <list<int>> adjList;//邻接链表
vector <node> Node; //结点数组
stack <int> rank;//分层后结果(栈顶到栈底,层次变低)
void bfs(){
queue<int> q;
list<int> l;
list<int>::iterator iter;
int cur,nxt;
node son; //第一个节点先进去
q.push(1);
rank.push(1);
//从第一层开始广度优先遍历
while(!q.empty()){
cur=q.front();//当前要访问的点
q.pop();
l=adjList[cur];//得到当前点的邻接点链表
for(iter=l.begin();iter!=l.end();iter++){
//将邻接点压入等待访问的队列
nxt=*iter;
if(!Node[nxt].visit){
q.push(nxt);//待访问
rank.push(nxt);
son=Node[nxt];
son.level=Node[cur].level+1;//确定层次 m
son.parent=cur;//确定父结点
Node[nxt]=son;
}
}
Node[cur].visit=1;//标记
}
}
int main(){
int n,i; cin>>n;
adjList.assign(n+1,list<int>());//n+1个链表
Node.assign(n+1,node());//n+1个点
for(i=1;i<=n;i++) cin>>Node[i].w; //权值
int l,r; //边
for(i=0;i<n-1;i++) {cin>>l>>r;
adjList[l].push_back(r);
adjList[r].push_back(l);}
bfs(); //确定层次和父结点
//动态规划自底向上根据每个节点的权值的正负,决定要不要贡献给父结点
int wei,cur,par;
while(!rank.empty()){
cur=rank.top();
rank.pop();
par=Node[cur].parent;
Node[par].w+=max(0,Node[cur].w);
}
int max=Node[1].w,maxi=1;
for(i=2;i<=n;i++)
{if(Node[i].w>max) {max=Node[i].w; maxi=i;}}
//cout<<"该树的最大连通分支的权值和是:"<<max<<'\n';
cout<<max;}
1821 判断完全二叉树(顺序存储)_牛客博客 (nowcoder.net)
//1821 E 完全二叉树
#include<stdio.h>
int find(int x,int y,int n,int a[],int *p) {int i;
for(i=1;i<=n;i++){
if(a[i]==x) {*p=i; return 1;}
if(a[i]==y) {*p=i; return 0;}}}
int judge(int a[],int n)
{int i; for(i=1;i<=n;i++) {if(a[i]==0) return 0;} return 1;}
int main(){
int n,g; scanf("%d%d",&n,&g);
int a[10000]={0};//初始化
a[1]=g;// 根节点进入数组
int x,y,i;
int p=0,max=1;//max代表数组最大长度
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
int flag=find(x,y,max,a,&p);//查找x,y中那个为根 指针带回根的位置
if(flag) {a[p*2]=y; if(p*2>max) max=p*2;}
else {a[p*2+1]=x; if(p*2+1>max) max=p*2+1;}}
int o=judge(a,max);//判断从a[1]到a[max]是否全为0
if(o==0) printf("no\n");
if(o==1) printf("yes\n");}
广义表表示的二叉树 ★ (7条消息) 按广义表表示二叉树结构生成二叉树链表的算法_二叉树广义表表示_WongKyunban的博客-CSDN博客
1801 B - 树与二叉树_b树和二叉树_米诺minoz的博客-CSDN博客
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLANK putchar(' ')
#define RETURN putchar('\n')
struct CHILD {int l; int r;} child[1001];
typedef struct BiTNode {char data; struct BiTNode *lchild,*rchild;} BiTNode,*BiTree;
void Preorder(BiTree T){
if(T!=NULL) {
printf("%c",T->data);
Preorder(T->lchild);
Preorder(T->rchild);}}
void Inorder(BiTree T){
if(T!=NULL) {
Inorder(T->lchild);
printf("%c",T->data);
Inorder(T->rchild);}}
void Postorder(BiTree T){
if(T!=NULL) {
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c",T->data);}}
int main() {
int n,i,m,flag=0; char c; BiTree node[1001];
scanf("%d",&n);
while(n--)
{
BiTree T; flag++; scanf("%d",&m); getchar();
for(i=1;i<=m;i++){
c=getchar(); scanf("%d %d",&child[i].l,&child[i].r);
getchar(); //%c %d %d fflush(stdin);
node[i]=(BiTree)malloc(sizeof(BiTNode));
node[i]->data=c;
}
T=node[1];
for(i=1;i<=m;i++)
{
if(child[i].l) node[i]->lchild=node[child[i].l];
else node[i]->lchild=NULL;
if(child[i].r) node[i]->rchild=node[child[i].r];
else node[i]->rchild=NULL;
}
printf("Case %d:\n",flag);
Preorder(T); RETURN;
Inorder(T); RETURN;
Postorder(T); RETURN;
}
}
1412 二叉树的繁茂度_Felven的博客-CSDN博客
#include <stdio.h>
#include <string.h>
int main(){char s[1000];
int i, up, sum, max, number, length, a[100];
scanf("%d",&number); while(number--)
{
up = max = sum = 0;
memset(a, 0, sizeof(a));
scanf("%s",&s); length=strlen(s);
for(i=0;i<length;i++)
{
if(s[i]!='(' && s[i]!=')' && s[i]!=',') a[up]++;
if(s[i]=='(') {up++; max++;}
if(s[i]==')') up--;
}
for(i=0;i<=max;i++) sum+=a[i]*i;
printf("%d\n",sum);
}}
1820 C 加分二叉树 - DWVictor - 博客园 (cnblogs.com)
需要调整一下格式(末尾无空格),用退格键不行\b,还是要用count==n?判断
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int n,v[39],f[47][47],i,j,k,root[49][49];
int count=1;
void print(int l,int r){
if(l>r)return;
if(l==r){
if(count==n) printf("%d",l);
else printf("%d ",l);
count++; return;}
if(count==n) printf("%d",root[l][r]);
else printf("%d ",root[l][r]);
count++;
print(l,root[l][r]-1);
print(root[l][r]+1,r);
}
int main() {
scanf("%d",&n);
for( i=1; i<=n; i++) scanf("%d",&v[i]);
for(i=1; i<=n; i++) {f[i][i]=v[i];f[i][i-1]=1;}
for(i=n; i>=1; i--)
for(j=i+1; j<=n; j++)
for(k=i; k<=j; k++) {
if(f[i][j]<(f[i][k-1]*f[k+1][j]+f[k][k])) {
f[i][j]=f[i][k-1]*f[k+1][j]+f[k][k];
root[i][j]=k;
}
}
printf("%d\n",f[1][n]);
print(1,n);
return 0;
}
2123 B(广义表生成二叉树)的高度和宽度
按广义表表示二叉树结构生成二叉树链表的算法_二叉树广义表表示_WongKyunban的博客-CSDN博客
A(B(,D(E,F)),C)
这里把 *str 换成 str[N] 了,如果不用这个的话 gets(str); 会出错
参考了下面这篇文章里的递归方法求解深度。容易出错的地方是n级指针,需要不断调……
(1条消息) 【二叉树基础】求二叉树的宽度_二叉树宽度算法_晚鹌鹑蛋的博客-CSDN博客
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 40
// 定义节点
typedef struct Node{
char data;
struct Node* lchild;
struct Node* rchild;
} Binode;
// 根据广义表表示二叉树结构来创建二叉树链表
Binode* createTree(char str[]){
Binode *st[100]; // 用指针数组st存放双亲节点
Binode *p = NULL; // 用来一生成节点时用的
Binode *b = NULL; // 二叉树链表的头节点
int top = -1,key,j=0;
char ch = str[j];
while(ch != '\0'){
// 在遍历广义表表示二叉树结构过程中,会遇到'(',',',')'和字母
switch(ch){
// 遇到'(',就是左子树,将key标记为1,以作记录,将当前节点记录到栈st中
case '(': top++; st[top] = p; key = 1; break; case ',': key = 2; break; // 遇到',',就是右子树,将key标记为1,以作记录
case ')': top--; break; // 遇到')',说明此子树已遍历完成,要返回到上一个双亲节点,准备遍历双亲节点的另一棵子树
default : // 遇到节点,为节点申请内存,并初始化节点
p = (Binode*)malloc(sizeof(Binode));
p->data = ch;
p->lchild = p->rchild = NULL;
// 记录头结点
if(b == NULL) b = p;
else {// 如果是非头结点,那么就根据key的值,将节点添加到双亲节点的子树上去
switch(key){
case 1: st[top]->lchild = p; break;
case 2: st[top]->rchild = p; break;}}}
j++; ch = str[j];}
return b;} // 返回头结点
void PreOrder(Binode *t){
if(t){ putchar(t->data);
PreOrder(t->lchild);
PreOrder(t->rchild);}}
//返回二叉树t的深度(高度)
int BitreeDepth(Binode *t){
int m, n;
if (t == NULL) return 0; //若是空树,深度为0,递归结束
m = BitreeDepth(t->lchild); //递归计算左子树的深度m
n = BitreeDepth(t->rchild);
return (m>n? m+1: n+1); }
int BitreeWidth(Binode *t, int k, int width[], int *max){
if (t == NULL) return 0;
width[k]++;
*max = *max > width[k]? *max : width[k];
BitreeWidth(t->lchild, k+1, width, max);
BitreeWidth(t->rchild, k+1, width, max);
}
int main(){
char str[N]; gets(str); //A(B(,D(E,F)),C)
Binode* t= createTree(str);
int max=0; int width[10]={0};
printf("%d ", BitreeDepth(t));
BitreeWidth(t,1,width,&max);
printf("%d",max);
}
1806 C 求二叉树中节点的深度
销毁树之后再生成就会出错,是因为没有分配空间,并且有缓冲区的影响,加这两句:
getchar(); /* 清除缓冲区 */ t=(BiNODE *)malloc(sizeof(BiNODE)); /* 初始化根节点 */
就可以解决多次生成销毁树带来的内存出错问题
比较坑,还好之前在王老师那道题碰到过销毁链表就出错的问题,
而且这个不检查、不报错,就更加坑了
//1806 C 求二叉树中节点的深度
#include <stdio.h>
#include <stdlib.h>
typedef enum {FALSE, TRUE} Boolean; //重命名枚举类型,枚举值为FALSE(0)和TRUE(1)
typedef char ElementType; //定义二叉树结点的数据类型为字符型
ElementType ERROR = -1; //特殊错误标志,须是正常的结点元素不可能取到的值
typedef struct BiNode {ElementType data; struct BiNode *lchild, *rchild;} BiNODE, *BiTree;
//访问二叉树结点函数,输出结点值
void PrintElement(ElementType e) {putchar(e);} //putchar(' ');
//先序遍历二叉树,其中形参Visit为指向函数的指针,实参为函数名
void PreOrderTraverse(BiTree t, void (*Visit)(ElementType))
{
if (t) //若二叉树为空,则空操作返回
{
(*Visit)(t->data); //访问根结点,*Visit是调用实参传进来的函数
PreOrderTraverse(t->lchild, Visit); //递归先序遍历左子树
PreOrderTraverse(t->rchild, Visit); //递归先序遍历右子树
}
}
//构造空的二叉树
void InitBiTree(BiTree *t) {*t = NULL;} //树的根结点置为空
//前序输入二叉树中结点的值构造二叉树
void CreateBiTree(BiTree *t)
{
//先创建根结点,再递归地创建左子树,之后递归地创建右子树。#表示空树。
//思考下:键盘输入abd#g###ce##f##[回车键]创建的二叉树。
//思考下:键盘输入abd g ce f [回车键]创建的二叉树。
ElementType ch; ch = getchar(); //从键盘输入字符,该字符是二叉树中结点的值
if (ch == ' ') *t = NULL; //输入' '代表空树,递归的终止条件,即递归出口
else
{
//生成根结点
*t = (BiNODE *)malloc(sizeof(BiNODE));
if (!*t) exit(1); //根结点空间分配失败,退出程序
(*t)->data = ch; //根结点的数据域赋值
CreateBiTree(&(*t)->lchild); //递归构造左子树
CreateBiTree(&(*t)->rchild); //递归构造右子树
}
}
//采用递归算法销毁根结点为root的二叉树
void DestoryBiTree(BiTree *t)
{
if (*t && (*t)->lchild) //若结点*t存在左子树
DestoryBiTree(&(*t)->lchild); //递归销毁*t的左子树
if (*t && (*t)->rchild) //若结点*t存在右子树
DestoryBiTree(&(*t)->rchild); //递归销毁*t的右子树
free(*t); //释放当前结点空间
*t = NULL; //结点删除之后,*t一定要置为空,这很重要
}
//判断二叉树t是否为空树
Boolean IsEmpty(BiTree t)
{
if (!t) return TRUE; //若t为空二叉树,返回TRUE
else return FALSE; //否则返回FALSE
}
//返回二叉树t的深度(高度)
int BiTreeDepth(BiTree t)
{
int m, n;
if (t == NULL) return 0; //若是空树,深度为0,递归结束
m = BiTreeDepth(t->lchild); //递归计算左子树的深度m
n = BiTreeDepth(t->rchild); //递归计算右子树的深度n
if (m > n) return m + 1; //二叉树的深度为左右子树深度较大者+1
else return n + 1;
}
int Maxlen(BiTree t, int *len){
if(!t) return 0;
int L = Maxlen(t->lchild, len);
int R = Maxlen(t->rchild, len);
*len = *len > L+R ? *len : L+R;
int max= L>R? L:R;
return 1+max;
}
BiNODE* Root(BiTree t) {return t;}
//返回二叉树t中结点p的值
ElementType Value(BiNODE *p) {
if (p) return p->data; else return ERROR;}
void Assign(BiNODE *p, ElementType e) {if (p) p->data = e;}
//根据LR为0或1,插入非空二叉树C为二叉树T中p所指结点的左或右子树,p所指结点的原有左或右子树则成为C的右子树。其中,非空树C和树T不相交且右子树为空
void InsertChild(BiNODE *p, int LR, BiTree c){
if (c == NULL) return; //如果c是空树,返回
if (LR == 0) {c->rchild = p->lchild; p->lchild = c;}
else if (LR == 1) {c->rchild = p->rchild; p->rchild = c;}}
//根据LR为0或1,删除二叉树T中p所指结点的左或右子树
void DeleteChild(BiNODE *p, int LR) {
if (LR == 0) if (p) DestoryBiTree(&p->lchild);
else if (LR == 1) if (p) DestoryBiTree(&p->rchild);}
//复制二叉树
BiTree CopyBiTree(BiTree t){
BiNODE *pNew; if (!t) return NULL;
pNew = (BiNODE *)malloc(sizeof(BiNODE));
pNew->data = t->data; //复制根结点的数据域
pNew->lchild = CopyBiTree(t->lchild); //递归复制左子树
pNew->rchild = CopyBiTree(t->rchild); //递归复制右子树
return pNew;}
//判断两棵树是否相等
Boolean BiTreeCmp(BiTree t1, BiTree t2){
if (!t1 && !t2) return TRUE; //若t1和t2皆为空树,则返回TRUE
//若t1和t2皆为非空树,则先比较根结点值,再递归比较左右子树
else if (t1 && t2 && (t1->data == t2->data) && BiTreeCmp(t1->lchild, t2->lchild) && BiTreeCmp(t1->rchild, t2->rchild)) return TRUE;
else return FALSE; //其他情况,则返回FALSE
}
int main(){
int times; char c; scanf("%d%c",×,&c);
while(times--){
BiTree t; InitBiTree(&t); CreateBiTree(&t); //构造二叉树t1
int len=0; printf("%d\n", Maxlen(t,&len));
DestoryBiTree(&t); getchar(); t=(BiNODE *)malloc(sizeof(BiNODE));
}}
1818 A HFM Basic
2275 F 简单哈夫曼树 :加一个while(times--){exec();}
这篇实在是太6了……多个愿望一次满足。加了void*指针类型强制转换不然gcc可能会编译失败。
哈夫曼树遍历求WPL和哈夫曼编码C语言--For初学者_哈夫曼树wpl c语言_a_52hz的博客-CSDN博客
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
typedef struct node
{
int weight;
struct node *lchild,*rchild;
struct node *next;
}HuffNode;
void HuffTree(HuffNode **);
void CreatUpLink(HuffNode **,int);
void InitLink(HuffNode**);
void PrintNode(HuffNode**);
void PrePrint(HuffNode *);
int CalcWPL(HuffNode *,int);
void HuffCode(HuffNode *,int);
int main(){
int wpl = 0; HuffNode *huff;
int n; scanf("%d",&n);
CreatUpLink(&huff,n);
//PrintNode(&huff);
HuffTree(&huff);
//printf("\nPreorder :\n");
//PrePrint(huff);
wpl = CalcWPL(huff,0);
printf("%d",wpl);
//printf("\n\nWPL = %d\n",wpl);
//printf("\nHuffCode:\n");
//HuffCode(huff,0);
//return 0;
}
int CalcWPL(HuffNode *huff,int wpl){
HuffNode *p = huff; if(!p) return 0; else {
if(!p->rchild&&!p->rchild) return p -> weight*wpl;
else return CalcWPL(p->lchild,wpl+1) + CalcWPL(p->rchild,wpl+1);}}
void HuffCode(HuffNode *huff,int len){
HuffNode *p = huff;
static int a[MAX];
int i;
if(p){
if(!p->lchild && !p->rchild){
printf("%d:",p->weight);
for(i = 0;i< len;i++) printf("%d",a[i]);
printf("\n");}
else {a[len] = 0; HuffCode(p->lchild,len+1);
a[len] = 1; HuffCode(p->rchild,len+1);}}}
void PrePrint(HuffNode *huff){
HuffNode *p = huff;
if(p){
printf("%d\t",p->weight);
PrePrint(p->lchild);
PrePrint(p->rchild);}}
void PrintNode(HuffNode **huff){
HuffNode *p = (*huff);
while(p) {printf("%d ",p->weight); p = p->next;}
putchar('\n');}
void InitLink(HuffNode **huff){(*huff) = NULL;}
void CreatUpLink(HuffNode **huff,int n){
HuffNode *pre,*p ,*s,*head = (*huff);
int x; scanf("%d",&x);
s = (HuffNode *)malloc(sizeof(HuffNode));
s -> lchild = NULL;
s -> rchild = NULL;
s -> weight = x;
s -> next = NULL;
head = s;
n--; while(n--){
pre = p = head;
scanf("%d",&x);
s = (HuffNode *)malloc(sizeof(HuffNode));
s->lchild = NULL;
s->rchild = NULL;
s->weight = x;
if(p->weight > x) {s-> next = p; head = s;}
else{
while(p && p->weight < x)
{pre = p; p = p->next;}
s -> next = pre->next;
pre -> next = s;}}
(*huff) = head;}
void HuffTree(HuffNode **huff){
HuffNode *pn1 ,*pn2 ,*p = *huff,*s = NULL,*q = NULL,*pre = NULL,*pr = NULL;
if(!p->next) return ;
while(p){
pn1 = p ;
pn2 = pn1 -> next;
pre = q = pn2 -> next ;
s = (HuffNode *)malloc(sizeof(HuffNode));
s -> lchild = pn1;
s -> rchild = pn2;
s -> weight = pn1 -> weight + pn2 -> weight;
s ->next = NULL;
if(!pn2 -> next){
s->next = NULL;
pn2->next = s;
(*huff) = s;
return;
}
if(pn2 -> next -> weight > s->weight)
{
s -> next = pn2 -> next;
pn2 ->next = s;
}
else
{
while(q && q->weight < s -> weight)
{
pre = q;
q = q->next;
}
s -> next = pre->next;
pre -> next = s;
}
pr = pn2;
p = pn2 -> next;
}
(*huff) = pr;
}
1818 F HFM coding
思路和教材上是一样的,就是没有读清楚题目
(每行第一个是元素个数,不是用~scanf扫描)
(6条消息) TOJ 1225 数据结构练习题——Huffman Coding_1225: 数据结构练习题――哈夫曼编码_芋智波佐助的博客-CSDN博客
//1818 F Huffman Coding
#include<stdio.h>
#define inf 0x7ffff;
struct node {int w,parent,lchild,rchild;} tree[202];
struct code {int start; int d[10];} huff[202];
int n;
void creat(){
int i,j,m,w1,w2,w,x,y; m=2*n-1;
for(i=1;i<=m;i++) tree[i].parent=tree[i].lchild=tree[i].rchild=0;
for(i=n+1;i<=m;i++)
{
w1=w2=inf; x=y=0;
for(j=1;j<i;j++){
if(!tree[j].parent){
if(w1>tree[j].w) {w2=w1; y=x; w1=tree[j].w; x=j;}
else if(w2>tree[j].w) {y=j; w2=tree[j].w;}}}
tree[i].w=w1+w2;
tree[x].parent=tree[y].parent=i;
tree[i].lchild=x;
tree[i].rchild=y;}}
void creat_huff(){
int i,c,f;
for(i=1;i<=n;i++){
huff[i].start=n;
for(c=i,f=tree[i].parent;f;c=f,f=tree[f].parent)
{if(c==tree[f].lchild) huff[i].d[huff[i].start--]=0;
else huff[i].d[huff[i].start--]=1;}}}
main(){int t,x,i; scanf("%d",&t);while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&tree[i].w);
creat(); creat_huff();
double sum=0.0;
for(i=1;i<=n;i++) sum+=n-huff[i].start;
sum/=n; printf("%.3f\n",sum);}}