您的位置:首页 > 理论基础 > 数据结构算法

【数据结构】求节点的哈夫曼的带权路径长度

2015-11-15 09:29 651 查看
题目来源:北航14级6系数据结构作业

【问题描述】

 已知输入一串正整数,正整数之间用空格键分开,请建立一个哈夫曼树,以输入的数字为叶节点,求这棵哈夫曼树的带权路径长度。
【输入形式】

 首先输入正整数的个数,然后接下来为接下来的正整数,正整数个数不超过10个
【输出形式】

 输出相应的权值
【样例输入】

 5 4 5 6 7 8
【样例输出】

 69

求哈夫曼树的算法用的是递归,然而并不会写非递归的,还要花时间研究一下,这次没有看清楚输入的要求,走了,不少的弯路,下次看题目一定要认真啊

#include <stdio.h>
#include <stdlib.h>

#define MAXNUM 20

typedef struct BTNode {
int data;
struct BTNode *lchild, *rchild;
}BTNode, *BTree;

typedef struct Node {
BTree bt;
struct Node *link;
} Node, *Forest;

void insertForestNode ( BTree t, Forest fr, Forest head);
void destoryBTree ( BTree t );
void getWPL( BTree t, int depth,  int *WPL);

int main() {

int num;
int n;
int i;
Forest head, top, fr, p, q;
BTree t, root, t1, t2;
int WPL = 0;

head = (Forest)malloc(sizeof(Node));
head->link = NULL;

scanf("%d",&n);
//用链式队列存森林
i = 1;
while( i <= n ) {

scanf("%d", &num);

t = (BTree)malloc(sizeof(BTNode));
t->data = num;
t->lchild = t->rchild = NULL;

fr = (Forest)malloc(sizeof(Node));
fr->bt = t;
fr->link = NULL;

//将元素从大到小排列
if( head->link == NULL) {
head->link= fr;
//top = fr;
}

else
insertForestNode(t,fr,head);

i++;
}

//构造哈夫曼树
while( head->link != NULL ) {

t = (BTree)malloc(sizeof(BTNode));
q = (Forest)malloc(sizeof(Node));
q->bt = t;
q->link = NULL;

t1 = head->link->bt;
p = head->link;
head->link = p->link;
t->lchild = t1;
free(p);

t2 = head->link->bt;
p = head->link;
head->link = p->link;
t->rchild = t2;
free(p);

t->data = t1->data + t2->data;
if(head->link != NULL)
insertForestNode(t,q,head);
}
free(head);

getWPL(t,0,&WPL);
printf("%d", WPL);

destoryBTree(t);
t = NULL;

return 0;
}

void insertForestNode ( BTree t, Forest fr, Forest head ) {

Forest p = head->link, q;

while ( p != NULL ) {

if( fr->bt->data > p->bt->data) {
q = p;
p = p->link;
}

else {
fr->link = p;

if( p == head->link)
head->link = fr;
else
q->link = fr;

break;
}

}

if( p == NULL)
q->link = fr;

}

//int getWPL ( BTree t) {
//
//    int depth = 0;
//    int top = -1;
//    int WPL = 0;
//    BTree Stack[MAXNUM];
//    BTree p;
//
//    p = t;
////    do{
////
////        while( p != NULL ) {
////            Stack[++top] = p;
////            p = p->lchild;
////            depth++;
////        }
////
////        p = Stack[top--];
////        WPL = WPL + p->data*(--depth);
////        p =
////
////    } while ( p != NULL || top != -1 );
//    do{
//
//        if( p->lchild != NULL && p->rchild != NULL ) {
//            Stack[++top] = p;
//            depth++;
//            p = p->lchild;
//
//        }
//
//        else {
//            WPL = WPL + p->data*(depth);
//            p = Stack[top]->rchild;
//            top--;
//
//        }
//    } while( top != -1);
//
//    return WPL;
//}

void getWPL( BTree t, int depth,  int *WPL) {
if( t->lchild == NULL && t->rchild == NULL) {
(*WPL) += depth*t->data;
}

else{
getWPL(t->lchild,depth+1,WPL);
getWPL(t->rchild,depth+1,WPL);
}

}

//二叉树的销毁
void destoryBTree ( BTree t ) {

if( t != NULL ) {
destoryBTree(t->lchild);
destoryBTree(t->rchild);
free(t);
}

}


经过某同学指点,利用了队列和按层次遍历,这下就可以有非递归算法了

先定义一个结构存有节点地址和其高度

struct depthBuffmanTree {
BTree bt;
int depth;
};

接着是
//非递归算法
int getWPL2(BTree t) {
struct depthBuffmanTree queue[MAXNUM];
struct depthBuffmanTree p;
int front = -1;
int rear = 0;
int WPL = 0;

queue[0].bt = t;
queue[0].depth = 0;

while( front < rear ) {
p = queue[++front];

if(p.bt->lchild == NULL && p.bt->rchild == NULL) {
WPL += p.bt->data*p.depth;
}

if( p.bt->lchild != NULL ) {
queue[++rear].bt = p.bt->lchild;
queue[rear].depth = p.depth + 1;
}

if( p.bt->rchild != NULL ) {
queue[++rear].bt = p.bt->rchild;
queue[rear].depth = p.depth + 1;
}

}

return WPL;

}

本文为我本人原创
我的邮箱:tao20dage@qq.com,欢迎交流
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: