大神帮我看一下哈夫曼树

训练有素的咸鱼 2018-05-16 09:36:58
我的哈夫曼树程序出了点问题
如果输入节点数大于6,可能会出现程序崩溃的情况,有时候明明是一样的数据,却会崩溃
像下面:

崩溃

可以

明明是一样的数据,为什么会出现这种结果?

求教各位

下面是代码
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
typedef struct Node{
int data;
Node *lchild;
Node *rchild;
}*Tree;

int num,n,s[1000],d[1000],wpl=0;
Node *a[1000];

void point(int m){
a[m-1] = (Node*)malloc(sizeof(Node));
a[m-1]->data = d[m-1];
if(m-1>0){
point(m-1);
}
}//创建节点,给其data赋值,并将节点存入a数组

void sort(){
Node *n;
for(int i=0;i<num-1;++i){
for(int j=i;j<num;++j){
if(a[i]->data<a[j]->data){
n=a[j]; a[j]=a[i]; a[i]=n;
}
}
}
}//选出最小的两个数字

void Build(){
Tree L = (Tree)malloc(sizeof(Tree));
Tree R = (Tree)malloc(sizeof(Tree));
Tree T = (Tree)malloc(sizeof(Tree));
sort();
T->data = a[num-1]->data + a[num-2]->data;
L = a[num-1];
R = a[num-2];
T->lchild = L;
T->rchild = R;
a[num-1] = 0;
--num;//合二元素为一,所以要减一
a[num-1]=T;
if(num>1){
Build();
}
}//构建哈夫曼树

int Deep(Node *T)
{
int deep=0;
if(T)
{
int leftdeep=0,rightdeep=0;
if(T->lchild != NULL && T->rchild != NULL){
leftdeep=Deep(T->lchild);
rightdeep=Deep(T->rchild);
deep=leftdeep>=rightdeep?leftdeep+1:deep=rightdeep+1;
}
}
return deep;
}

void Preorder(Node *T,int which,int n){
if(which == 0){
n = n*2;
}
if(which == 1){
n = n*2 + 1;
}
if(T->data != 0){
printf(" %d",T->data);
s[n-1] = T->data;//存入数组
if(T->lchild != NULL && T->rchild != NULL){
Preorder(T->lchild,0,n);
Preorder(T->rchild,1,n);
}
}
}

void InOrder(Node *T){
if(T == NULL){
return;
}
if(T != NULL){
if(T->lchild != NULL && T->rchild != NULL){
InOrder(T->lchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
}
printf(" %d",T->data);//输出
if(T->lchild != NULL && T->rchild != NULL){
InOrder(T->rchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
}
//到达最左,输出其及父节点值,再是其右节点(如果有),然后返回上一级
}
}

void PostOrder(Node *T){
if(T == NULL){
return;
}
if(T != NULL){
if(T->lchild != NULL && T->rchild != NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
}
printf(" %d",T->data);
//输出完左返回上一级输出右然后再输出根
}
}

void space(int n){
for(int i=0;i<n;++i){
printf(" ");
}
}

int digit(int n){
int d=1,m=1;
while(d != 0){
d=n/int(pow(10,m))%10;
++m;
}
return m-1;//获得位数,即占位空间
}

void showTree(int deep,int layer){//深度,层编号(从树根开始依次增大)
int k = pow(2,layer-1);
int m = pow(2,layer);
printf("\n ");
//输出值
for(int i = k-1;i<m-1;++i){
space(pow(2,deep-layer));
s[i]==0 ? printf("*"):printf("%d",s[i]);
space(pow(2,deep-layer)-digit(s[i]));
if(i==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
}

if(layer<deep){
//换输出箭头
printf("\n ");
for(int j = k-1;j<m-1;++j){
space(pow(2,deep-layer));
s[j]==0 ? printf("/\\"):printf("/\\");
space(pow(2,deep-layer)-2);
if(j==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
}
//递归
showTree(deep,layer+1);
}
}

void WPL(int deep,int layer){//深度,层编号(从树根开始依次增大)
for(int i = pow(2,layer-1)-1;i<pow(2,layer)-1;++i){
for(int w=0;w<1000;++w){
if(d[w] == s[i] && d[w] != 0){
wpl=wpl+s[i]*(layer-1);
}
}
}
if(layer<=deep){
WPL(deep,layer+1);
}
}

int main(){
printf(" -------------------------------------------------------------------------\n|可视化哈夫曼树\n| ");
printf("\n|二叉树可视化注意事项");
printf("\n|以树根为第1层,数的深度为第n层");
printf("\n|1.建议输入最小两个数均不大于10");
printf("\n|2.由于控制台最大限制,节点超过13不显示二叉树结构!\n|3.二叉树生成可能有一定的变形");
printf("\n|4./\\指向左右子节点,*表示节点为空\n|5.当二叉树出现变形,可以4为参考判断节点从属关系");
printf("\n|\n|可能的运行错误警告\n|1.节点超过6,程序有几率崩溃,只能重新运行并输入,直到程序正常运行为止");
printf("\n|2.节点超过6,二叉树data有很小概率出错,重新运行即可");
printf("\n -------------------------------------------------------------------------\n");
printf(" 输入哈夫曼树节点个数(1<n<=1000):");
scanf("%d",&num);
if(num<2){
printf(" 输入不合法,节点数强制改为2!\n");num=2;
}
if(num>1000){
printf(" 输入不合法,节点数强制改为1000!\n");num=1000;
}
n=num;
for(int i=0;i<num;++i){
printf(" 第%d个节点:",i+1);
scanf("%d",&d[i]);
}

point(num);
Build();
printf(" 先序遍历:");
Preorder(a[0],2,1);
printf("\n 中序遍历:");
InOrder(a[0]);
printf("\n 后序遍历:");
PostOrder(a[0]);
WPL(Deep(a[0]),1);
printf("\n 带权路径长度:%d",wpl);
if(Deep(a[0])<8){
printf("\n\n 二叉树结构:*表示为空,/\\表示指向左右子节点\n");
showTree(Deep(a[0])+1,1);
}
if(Deep(a[0])>7){
printf("\n深度过大,无法正常显示!!");
}
}
...全文
1111 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
舉杯邀明月 2018-05-22
  • 打赏
  • 举报
回复
赵四经常只是空谈理论,这次倒是直接解决问题,真是难得啊。 这帖子,我是不是应该收藏一下……
  • 打赏
  • 举报
回复
嗯,谢谢指点,那我结贴了。
赵4老师 2018-05-21
  • 打赏
  • 举报
回复
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒:再牛×的老师也无法代替学生自己领悟和上厕所! 单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
赵4老师 2018-05-21
  • 打赏
  • 举报
回复
用来填空的字数不到1000字,不给分。
  • 打赏
  • 举报
回复
赵老师答疑专用楼层
  • 打赏
  • 举报
回复
引用 26 楼 zhao4zhong1 的回复:
大神之所以成为大神,是因为____________________________(此空填写的字数不得少于1000字!)。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
typedef struct Node{
    int data;
    Node *lchild;
    Node *rchild;
}*Tree;

int num,n,s[1000],d[1000],wpl=0;
Node *a[1000];
int mypow(int v,int e) {
    if (e<=0) return 1;
    if (e==1) return v;
    int i,r;
    r=1;
    for (i=0;i<e;i++) r*=v;
    return r;
}
void point(int m){
    a[m-1] = (Node*)malloc(sizeof(Node));
    a[m-1]->data = d[m-1];
    a[m-1]->lchild=NULL;
    a[m-1]->rchild=NULL;
    if(m-1>0){
        point(m-1);
    }
}//创建节点,给其data赋值,并将节点存入a数组

void sort(){
    Node *n;
    for(int i=0;i<num-1;++i){
        for(int j=i+1;j<num;++j){
            if(a[i]->data<a[j]->data){
                n=a[j]; a[j]=a[i]; a[i]=n;
            }
        }
    }
}//选出最小的两个数字

void Build(){
    Tree L = (Tree)malloc(sizeof(Tree));
    Tree R = (Tree)malloc(sizeof(Tree));
    Tree T = (Tree)malloc(sizeof(Node));
    sort();
    T->data = a[num-1]->data + a[num-2]->data;
    L = a[num-1];
    R = a[num-2];
    T->lchild = L;
    T->rchild = R;
    a[num-1] = 0;
    --num;//合二元素为一,所以要减一
    a[num-1]=T;
    if(num>1){
        Build();
    }
}//构建哈夫曼树

int Deep(Node *T)
{
    int deep=0;
    if(T)
    {
        int leftdeep=0,rightdeep=0;
        if(T->lchild != NULL && T->rchild != NULL){
            leftdeep=Deep(T->lchild);
            rightdeep=Deep(T->rchild);
            deep=leftdeep>=rightdeep?leftdeep+1:deep=rightdeep+1;
        }
    }
    return deep;
}

void Preorder(Node *T,int which,int n){
    if(which == 0){
        n = n*2;
    }
    if(which == 1){
        n = n*2 + 1;
    }
    if(T->data != 0){
        printf(" %d",T->data);
        s[n-1] = T->data;//存入数组
        if(T->lchild != NULL && T->rchild != NULL){
            Preorder(T->lchild,0,n);
            Preorder(T->rchild,1,n);
        }
    }
}

void InOrder(Node *T){
    if(T == NULL){
        return;
    }
    if(T != NULL){
        if(T->lchild != NULL && T->rchild != NULL){
            InOrder(T->lchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
        }
        printf(" %d",T->data);//输出
        if(T->lchild != NULL && T->rchild != NULL){
            InOrder(T->rchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
        }
        //到达最左,输出其及父节点值,再是其右节点(如果有),然后返回上一级
    }
}

void PostOrder(Node *T){
    if(T == NULL){
        return;
    }
    if(T != NULL){
        if(T->lchild != NULL && T->rchild != NULL){
            PostOrder(T->lchild);
            PostOrder(T->rchild);
        }
        printf(" %d",T->data);
        //输出完左返回上一级输出右然后再输出根
    }
}

void space(int n){
    for(int i=0;i<n;++i){
        printf(" ");
    }
}

int digit(int n){
    int d=1,m=1;
    while(d != 0){
        d=n/int(mypow(10,m))%10;
        ++m;
    }
    return m-1;//获得位数,即占位空间
}

void showTree(int deep,int layer){//深度,层编号(从树根开始依次增大)
    int k = mypow(2,layer-1);
    int m = mypow(2,layer);
    printf("\n ");
    //输出值
    for(int i = k-1;i<m-1;++i){
        space(mypow(2,deep-layer));
        s[i]==0 ? printf("*"):printf("%d",s[i]);
        space(mypow(2,deep-layer)-digit(s[i]));
        if(i==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
    }

    if(layer<deep){
        //换输出箭头
        printf("\n ");
        for(int j = k-1;j<m-1;++j){
            space(mypow(2,deep-layer));
            s[j]==0 ? printf("/\\"):printf("/\\");
            space(mypow(2,deep-layer)-2);
            if(j==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
        }
        //递归
        showTree(deep,layer+1);
    }
}

void WPL(int deep,int layer){//深度,层编号(从树根开始依次增大)
    for(int i = mypow(2,layer-1)-1;i<mypow(2,layer)-1;++i){
        for(int w=0;w<1000;++w){
            if(d[w] == s[i] && d[w] != 0){
                wpl=wpl+s[i]*(layer-1);
            }
        }
    }
    if(layer<=deep){
        WPL(deep,layer+1);
    }
}

int main(){
    printf(" -------------------------------------------------------------------------\n|可视化哈夫曼树\n|  ");
    printf("\n|二叉树可视化注意事项");
    printf("\n|以树根为第1层,数的深度为第n层");
    printf("\n|1.建议输入最小两个数均不大于10");
    printf("\n|2.由于控制台最大限制,节点超过13不显示二叉树结构!\n|3.二叉树生成可能有一定的变形");
    printf("\n|4./\\指向左右子节点,*表示节点为空\n|5.当二叉树出现变形,可以4为参考判断节点从属关系");
    printf("\n -------------------------------------------------------------------------\n");
    printf(" 输入哈夫曼树节点个数(1<n<=1000):");
    scanf("%d",&num);
    if(num<2){
        printf(" 输入不合法,节点数强制改为2!\n");num=2;
    }
    if(num>1000){
        printf(" 输入不合法,节点数强制改为1000!\n");num=1000;
    }
    n=num;
    for(int i=0;i<num;++i){
        printf(" 第%d个节点:",i+1);
        scanf("%d",&d[i]);
    }

    point(num);
    Build();
    printf("\n先序遍历:");
    Preorder(a[0],2,1);
    printf("\n 中序遍历:");
    InOrder(a[0]);
    printf("\n 后序遍历:");
    PostOrder(a[0]);
    WPL(Deep(a[0]),1);
    printf("\n 带权路径长度:%d",wpl);
    if(Deep(a[0])<8){
        printf("\n\n 二叉树结构:*表示为空,/\\表示指向左右子节点\n");
        showTree(Deep(a[0])+1,1);
    }
    if(Deep(a[0])>7){
        printf("\n深度过大,无法正常显示!!");
    }
    return 0;
}
膜拜大哥 这下错误率彻底为0了 嗯,所以之前为啥会报错?
赵4老师 2018-05-21
  • 打赏
  • 举报
回复
大神之所以成为大神,是因为____________________________(此空填写的字数不得少于1000字!)。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
typedef struct Node{
    int data;
    Node *lchild;
    Node *rchild;
}*Tree;

int num,n,s[1000],d[1000],wpl=0;
Node *a[1000];
int mypow(int v,int e) {
    if (e<=0) return 1;
    if (e==1) return v;
    int i,r;
    r=1;
    for (i=0;i<e;i++) r*=v;
    return r;
}
void point(int m){
    a[m-1] = (Node*)malloc(sizeof(Node));
    a[m-1]->data = d[m-1];
    a[m-1]->lchild=NULL;
    a[m-1]->rchild=NULL;
    if(m-1>0){
        point(m-1);
    }
}//创建节点,给其data赋值,并将节点存入a数组

void sort(){
    Node *n;
    for(int i=0;i<num-1;++i){
        for(int j=i+1;j<num;++j){
            if(a[i]->data<a[j]->data){
                n=a[j]; a[j]=a[i]; a[i]=n;
            }
        }
    }
}//选出最小的两个数字

void Build(){
    Tree L = (Tree)malloc(sizeof(Tree));
    Tree R = (Tree)malloc(sizeof(Tree));
    Tree T = (Tree)malloc(sizeof(Node));
    sort();
    T->data = a[num-1]->data + a[num-2]->data;
    L = a[num-1];
    R = a[num-2];
    T->lchild = L;
    T->rchild = R;
    a[num-1] = 0;
    --num;//合二元素为一,所以要减一
    a[num-1]=T;
    if(num>1){
        Build();
    }
}//构建哈夫曼树

int Deep(Node *T)
{
    int deep=0;
    if(T)
    {
        int leftdeep=0,rightdeep=0;
        if(T->lchild != NULL && T->rchild != NULL){
            leftdeep=Deep(T->lchild);
            rightdeep=Deep(T->rchild);
            deep=leftdeep>=rightdeep?leftdeep+1:deep=rightdeep+1;
        }
    }
    return deep;
}

void Preorder(Node *T,int which,int n){
    if(which == 0){
        n = n*2;
    }
    if(which == 1){
        n = n*2 + 1;
    }
    if(T->data != 0){
        printf(" %d",T->data);
        s[n-1] = T->data;//存入数组
        if(T->lchild != NULL && T->rchild != NULL){
            Preorder(T->lchild,0,n);
            Preorder(T->rchild,1,n);
        }
    }
}

void InOrder(Node *T){
    if(T == NULL){
        return;
    }
    if(T != NULL){
        if(T->lchild != NULL && T->rchild != NULL){
            InOrder(T->lchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
        }
        printf(" %d",T->data);//输出
        if(T->lchild != NULL && T->rchild != NULL){
            InOrder(T->rchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
        }
        //到达最左,输出其及父节点值,再是其右节点(如果有),然后返回上一级
    }
}

void PostOrder(Node *T){
    if(T == NULL){
        return;
    }
    if(T != NULL){
        if(T->lchild != NULL && T->rchild != NULL){
            PostOrder(T->lchild);
            PostOrder(T->rchild);
        }
        printf(" %d",T->data);
        //输出完左返回上一级输出右然后再输出根
    }
}

void space(int n){
    for(int i=0;i<n;++i){
        printf(" ");
    }
}

int digit(int n){
    int d=1,m=1;
    while(d != 0){
        d=n/int(mypow(10,m))%10;
        ++m;
    }
    return m-1;//获得位数,即占位空间
}

void showTree(int deep,int layer){//深度,层编号(从树根开始依次增大)
    int k = mypow(2,layer-1);
    int m = mypow(2,layer);
    printf("\n ");
    //输出值
    for(int i = k-1;i<m-1;++i){
        space(mypow(2,deep-layer));
        s[i]==0 ? printf("*"):printf("%d",s[i]);
        space(mypow(2,deep-layer)-digit(s[i]));
        if(i==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
    }

    if(layer<deep){
        //换输出箭头
        printf("\n ");
        for(int j = k-1;j<m-1;++j){
            space(mypow(2,deep-layer));
            s[j]==0 ? printf("/\\"):printf("/\\");
            space(mypow(2,deep-layer)-2);
            if(j==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
        }
        //递归
        showTree(deep,layer+1);
    }
}

void WPL(int deep,int layer){//深度,层编号(从树根开始依次增大)
    for(int i = mypow(2,layer-1)-1;i<mypow(2,layer)-1;++i){
        for(int w=0;w<1000;++w){
            if(d[w] == s[i] && d[w] != 0){
                wpl=wpl+s[i]*(layer-1);
            }
        }
    }
    if(layer<=deep){
        WPL(deep,layer+1);
    }
}

int main(){
    printf(" -------------------------------------------------------------------------\n|可视化哈夫曼树\n|  ");
    printf("\n|二叉树可视化注意事项");
    printf("\n|以树根为第1层,数的深度为第n层");
    printf("\n|1.建议输入最小两个数均不大于10");
    printf("\n|2.由于控制台最大限制,节点超过13不显示二叉树结构!\n|3.二叉树生成可能有一定的变形");
    printf("\n|4./\\指向左右子节点,*表示节点为空\n|5.当二叉树出现变形,可以4为参考判断节点从属关系");
    printf("\n -------------------------------------------------------------------------\n");
    printf(" 输入哈夫曼树节点个数(1<n<=1000):");
    scanf("%d",&num);
    if(num<2){
        printf(" 输入不合法,节点数强制改为2!\n");num=2;
    }
    if(num>1000){
        printf(" 输入不合法,节点数强制改为1000!\n");num=1000;
    }
    n=num;
    for(int i=0;i<num;++i){
        printf(" 第%d个节点:",i+1);
        scanf("%d",&d[i]);
    }

    point(num);
    Build();
    printf("\n先序遍历:");
    Preorder(a[0],2,1);
    printf("\n 中序遍历:");
    InOrder(a[0]);
    printf("\n 后序遍历:");
    PostOrder(a[0]);
    WPL(Deep(a[0]),1);
    printf("\n 带权路径长度:%d",wpl);
    if(Deep(a[0])<8){
        printf("\n\n 二叉树结构:*表示为空,/\\表示指向左右子节点\n");
        showTree(Deep(a[0])+1,1);
    }
    if(Deep(a[0])>7){
        printf("\n深度过大,无法正常显示!!");
    }
    return 0;
}
  • 打赏
  • 举报
回复
引用 21 楼 Chen8013 的回复:
[quote=引用 18 楼 qq_40636117 的回复:] [quote=引用 15 楼 Chen8013 的回复:] [quote=引用 14 楼 zhao4zhong1 的回复:] Orz 跪谢楼上帮断帖之恩当涌泉相报!
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
// . . . . . . . .
刚好在线, 举手之劳而已,不用说得这么夸张吧。 [/quote] 谢谢大神,崩溃的概率小了很多[/quote] 你这儿应该引用14楼吧,我只是来灌水,断一下楼而已,帮你解决问题的是赵4。 [/quote]啥是断贴?不懂
  • 打赏
  • 举报
回复
是不是应用不能超过三次啊,烦
  • 打赏
  • 举报
回复
引用 19 楼 zhao4zhong1 的回复:
[quote=引用 18 楼 qq_40636117 的回复:]
[quote=引用 15 楼 Chen8013 的回复:]
[quote=引用 14 楼 zhao4zhong1 的回复:]
Orz 跪谢楼上帮断帖之恩当涌泉相报!
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
// . . . . . . . .

刚好在线, 举手之劳而已,不用说得这么夸张吧。
[/quote]

谢谢大神,崩溃的概率小了很多[/quote]
应该是0才对。[/quote]节点在10以内几乎不崩溃,节点为10的崩溃大概在一半,节点数为11的几乎8成崩溃,节点数为12的没有不崩溃的


我重新安装了vs,可以调试了,但是找不到链接器,听说要去找库资源管理器,可是找不到啊


我的是vs2013
舉杯邀明月 2018-05-19
  • 打赏
  • 举报
回复
这论坛,只允许“连续回复3次”啊………… 赵4 在10到12楼回复,已经连续3次了。 但他还有“更重要的内容”需要回复,   如果没别人来“断一下”,他是没法回复的,   但无论怎么“想”,也只能“憋着”……必须等到有别人的回复之后才行。 因此,我就来随便回复一下,解他的“燃眉之急”了。
舉杯邀明月 2018-05-18
  • 打赏
  • 举报
回复
赵4老师 2018-05-18
  • 打赏
  • 举报
回复
Orz 跪谢楼上帮断帖之恩当涌泉相报!
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
typedef struct Node{
    int data;
    Node *lchild;
    Node *rchild;
}*Tree;

int num,n,s[1000],d[1000],wpl=0;
Node *a[1000];
int mypow(int v,int e) {
    if (e<=0) return 1;
    if (e==1) return v;
    int i,r;
    r=1;
    for (i=0;i<e;i++) r*=v;
    return r;
}
void point(int m){
    a[m-1] = (Node*)malloc(sizeof(Node));
    a[m-1]->data = d[m-1];
    a[m-1]->lchild=NULL;
    a[m-1]->rchild=NULL;
    if(m-1>0){
        point(m-1);
    }
}//创建节点,给其data赋值,并将节点存入a数组

void sort(){
    Node *n;
    for(int i=0;i<num-1;++i){
        for(int j=i;j<num;++j){
            if(a[i]->data<a[j]->data){
                n=a[j]; a[j]=a[i]; a[i]=n;
            }
        }
    }
}//选出最小的两个数字

void Build(){
    Tree L = (Tree)malloc(sizeof(Tree));
    Tree R = (Tree)malloc(sizeof(Tree));
    Tree T = (Tree)malloc(sizeof(Tree));
    sort();
    T->data = a[num-1]->data + a[num-2]->data;
    L = a[num-1];
    R = a[num-2];
    T->lchild = L;
    T->rchild = R;
    a[num-1] = 0;
    --num;//合二元素为一,所以要减一
    a[num-1]=T;
    if(num>1){
        Build();
    }
}//构建哈夫曼树

int Deep(Node *T)
{
    int deep=0;
    if(T)
    {
        int leftdeep=0,rightdeep=0;
        if(T->lchild != NULL && T->rchild != NULL){
            leftdeep=Deep(T->lchild);
            rightdeep=Deep(T->rchild);
            deep=leftdeep>=rightdeep?leftdeep+1:deep=rightdeep+1;
        }
    }
    return deep;
}

void Preorder(Node *T,int which,int n){
    if(which == 0){
        n = n*2;
    }
    if(which == 1){
        n = n*2 + 1;
    }
    if(T->data != 0){
        printf(" %d",T->data);
        s[n-1] = T->data;//存入数组
        if(T->lchild != NULL && T->rchild != NULL){
            Preorder(T->lchild,0,n);
            Preorder(T->rchild,1,n);
        }
    }
}

void InOrder(Node *T){
    if(T == NULL){
        return;
    }
    if(T != NULL){
        if(T->lchild != NULL && T->rchild != NULL){
            InOrder(T->lchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
        }
        printf(" %d",T->data);//输出
        if(T->lchild != NULL && T->rchild != NULL){
            InOrder(T->rchild);//先遍历,到达二叉树最左 (该节点没有左子,否则不是二叉树最左)
        }
        //到达最左,输出其及父节点值,再是其右节点(如果有),然后返回上一级
    }
}

void PostOrder(Node *T){
    if(T == NULL){
        return;
    }
    if(T != NULL){
        if(T->lchild != NULL && T->rchild != NULL){
            PostOrder(T->lchild);
            PostOrder(T->rchild);
        }
        printf(" %d",T->data);
        //输出完左返回上一级输出右然后再输出根
    }
}

void space(int n){
    for(int i=0;i<n;++i){
        printf(" ");
    }
}

int digit(int n){
    int d=1,m=1;
    while(d != 0){
        d=n/int(mypow(10,m))%10;
        ++m;
    }
    return m-1;//获得位数,即占位空间
}

void showTree(int deep,int layer){//深度,层编号(从树根开始依次增大)
    int k = mypow(2,layer-1);
    int m = mypow(2,layer);
    printf("\n ");
    //输出值
    for(int i = k-1;i<m-1;++i){
        space(mypow(2,deep-layer));
        s[i]==0 ? printf("*"):printf("%d",s[i]);
        space(mypow(2,deep-layer)-digit(s[i]));
        if(i==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
    }

    if(layer<deep){
        //换输出箭头
        printf("\n ");
        for(int j = k-1;j<m-1;++j){
            space(mypow(2,deep-layer));
            s[j]==0 ? printf("/\\"):printf("/\\");
            space(mypow(2,deep-layer)-2);
            if(j==(k+m-3)/2){space(1);}//如果处于该层中间,还要多输出一个空格
        }
        //递归
        showTree(deep,layer+1);
    }
}

void WPL(int deep,int layer){//深度,层编号(从树根开始依次增大)
    for(int i = mypow(2,layer-1)-1;i<mypow(2,layer)-1;++i){
        for(int w=0;w<1000;++w){
            if(d[w] == s[i] && d[w] != 0){
                wpl=wpl+s[i]*(layer-1);
            }
        }
    }
    if(layer<=deep){
        WPL(deep,layer+1);
    }
}

int main(){
    printf(" -------------------------------------------------------------------------\n|可视化哈夫曼树\n|  ");
    printf("\n|二叉树可视化注意事项");
    printf("\n|以树根为第1层,数的深度为第n层");
    printf("\n|1.建议输入最小两个数均不大于10");
    printf("\n|2.由于控制台最大限制,节点超过13不显示二叉树结构!\n|3.二叉树生成可能有一定的变形");
    printf("\n|4./\\指向左右子节点,*表示节点为空\n|5.当二叉树出现变形,可以4为参考判断节点从属关系");
    printf("\n -------------------------------------------------------------------------\n");
    printf(" 输入哈夫曼树节点个数(1<n<=1000):");
    scanf("%d",&num);
    if(num<2){
        printf(" 输入不合法,节点数强制改为2!\n");num=2;
    }
    if(num>1000){
        printf(" 输入不合法,节点数强制改为1000!\n");num=1000;
    }
    n=num;
    for(int i=0;i<num;++i){
        printf(" 第%d个节点:",i+1);
        scanf("%d",&d[i]);
    }

    point(num);
    Build();
    printf(" 先序遍历:");
    Preorder(a[0],2,1);
    printf("\n 中序遍历:");
    InOrder(a[0]);
    printf("\n 后序遍历:");
    PostOrder(a[0]);
    WPL(Deep(a[0]),1);
    printf("\n 带权路径长度:%d",wpl);
    if(Deep(a[0])<8){
        printf("\n\n 二叉树结构:*表示为空,/\\表示指向左右子节点\n");
        showTree(Deep(a[0])+1,1);
    }
    if(Deep(a[0])>7){
        printf("\n深度过大,无法正常显示!!");
    }
    return 0;
}
// -------------------------------------------------------------------------
//|可视化哈夫曼树
//|
//|二叉树可视化注意事项
//|以树根为第1层,数的深度为第n层
//|1.建议输入最小两个数均不大于10
//|2.由于控制台最大限制,节点超过13不显示二叉树结构!
//|3.二叉树生成可能有一定的变形
//|4./\指向左右子节点,*表示节点为空
//|5.当二叉树出现变形,可以4为参考判断节点从属关系
// -------------------------------------------------------------------------
// 输入哈夫曼树节点个数(1<n<=1000):8
// 第1个节点:2
// 第2个节点:22
// 第3个节点:6
// 第4个节点:20
// 第5个节点:3
// 第6个节点:10
// 第7个节点:7
// 第8个节点:30
// 先序遍历: 100 42 20 22 58 28 11 5 2 3 6 17 7 10 30
// 中序遍历: 20 42 22 100 2 5 3 11 6 28 7 17 10 58 30
// 后序遍历: 20 22 42 2 3 5 6 11 7 10 17 28 30 58 100
// 带权路径长度:261
//
// 二叉树结构:*表示为空,/\表示指向左右子节点
//
//                                 100
//                                 /\
//                 42                               58
//                 /\                               /\
//         20              22               28              30
//         /\              /\               /\              /\
//     *       *       *       *        11      17      *       *
//     /\      /\      /\      /\       /\      /\      /\      /\
//   *   *   *   *   *   *   *   *    5   6   7   10  *   *   *   *
//   /\  /\  /\  /\  /\  /\  /\  /\   /\  /\  /\  /\  /\  /\  /\  /\
//  * * * * * * * * * * * * * * * *  2 3 * * * * * * * * * * * * * *
//
赵4老师 2018-05-18
  • 打赏
  • 举报
回复
第8个节点你输入的一个是3,一个是30,一样吗?
赵4老师 2018-05-18
  • 打赏
  • 举报
回复
第8个数据一个是3,一个是30,一样吗?
赵4老师 2018-05-18
  • 打赏
  • 举报
回复
Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt 仅供参考:
#include <iostream>
#include <string>
using namespace std;
struct huffTree {
    int parent;
    int lchild;
    int rchild;
    int weight;
    string flag;
};
struct Lowest_node {
    char ch;
    int ch_num;
};
void coding(int length,huffTree *tree,int n,int &a,int &b) {
    int i;
    int r,s;

    r=s=length;
    for (i=0;i<n;i++) {
        if (tree[i].weight<r
         && tree[i].parent==-1) {
            r=tree[i].weight;
            a=i;
        }
    }
    for (i=0;i<n;i++) {
        if (tree[i].weight<s
         && i!=a
         && tree[i].parent==-1) {
            s=tree[i].weight;
            b=i;
        }
    }
}
void frequency(string str) {
    int i,j;
    int length=str.length();
    Lowest_node *node=new Lowest_node[length];

    for (i=0;i<length;i++) node[i].ch_num=0;

    int char_type_num=0;
    for (i=0;i<length;i++) {
        for (j=0;j<char_type_num;j++)
            if (str[i]==node[j].ch
            || ('a'<=node[j].ch && node[j].ch<='z'
                && str[i]+32==node[j].ch))
                break;//
        if (j<char_type_num) node[j].ch_num++;
        else {
            if ('A'<=str[i] && str[i] <= 'Z') node[j].ch=str[i]+32;
            else node[j].ch=str[i];
            node[j].ch_num++;
            char_type_num++;
        }
    }
    for (i=0;i<char_type_num;i++) {
        for (j=i;j<char_type_num;j++) {
            if (node[j].ch_num<node[j+1].ch_num) {
                int temp;
                char ch_temp;
                temp=node[j].ch_num;
                ch_temp=node[j].ch;
                node[j].ch_num=node[j+1].ch_num;
                node[j].ch=node[j+1].ch;
                node[j+1].ch_num=temp;
                node[j+1].ch=ch_temp;
            }
        }
    }
    for (i=0;i<char_type_num;i++)
        cout<<"字符"<<node[i].ch<<"出现了"<<node[i].ch_num<<"次"<<endl;
    huffTree *huff=new huffTree[2*char_type_num-1];
    huffTree temp;
    string *code=new string[2*char_type_num-1];

    for (i=0;i<2*char_type_num-1;i++) {
        huff[i].lchild=-1;
        huff[i].parent=-1;
        huff[i].rchild=-1;
        huff[i].flag=-1;
    }
    for (j=0;j<char_type_num;j++) huff[j].weight=node[j].ch_num;
    int min1,min2;
    for (int k=char_type_num;k<2*char_type_num-1;k++) {
        coding(length,huff,k,min1,min2);
        huff[min1].parent=k;
        huff[min2].parent=k;
        huff[min1].flag="0";
        huff[min2].flag="1";
        huff[k].lchild=min1;
        huff[k].rchild=min2;
        huff[k].weight=huff[min1].weight+huff[min2].weight;
    }
    for (i=0;i<char_type_num;i++) {
        temp=huff[i];
        while (1) {
            code[i]=temp.flag+code[i];
            temp=huff[temp.parent];
            if (temp.parent==-1) break;//
        }
    }
    cout<<"字符串的每个字符huffman编码为:"<<endl;
    for (i=0;i<char_type_num;i++) cout<<node[i].ch<<"  "<<code[i]<<endl;
    cout<<"整个字符串的huffman编码为:"<<endl;
    for (i=0;i<length;i++) {                                                                                     //S?
        for (j=0;j<char_type_num;j++) {
            if (str[i]==node[j].ch)
                cout<<code[j];
        }
    }
    delete[] node;
    node=NULL;
    delete[] huff;
    huff=NULL;
    delete[] code;
    code=NULL;
}
int main() {
    int length=0;
    string str;
    cout<<"请输入一个字符串:";
    cin>>str;
    frequency(str);
    return 0;
}
//请输入一个字符串:2333abcde
//字符3出现了3次
//字符2出现了1次
//字符a出现了1次
//字符b出现了1次
//字符c出现了1次
//字符d出现了1次
//字符e出现了1次
//字符串的每个字符huffman编码为:
//3  11
//2  000
//a  001
//b  010
//c  011
//d  100
//e  101
//整个字符串的huffman编码为:
//000111111001010011100101
JamesWu9527 2018-05-18
  • 打赏
  • 举报
回复
引用 8 楼 qq_40636117 的回复:
引用 6 楼 Wuzm_ 的回复:
[quote=引用 3 楼 qq_40636117 的回复:] [quote=引用 2 楼 Wuzm_ 的回复:] 因为malloc和free是成对出现的,申请了内存用完了就得释放 = =
树的内存还要存放东西,没有用完啊
在build中 第一次申请内存后 然后递归build 就在那里挂的;[/quote] 只有数组元素最少为1的时候才执行递归,递归申请的三个内存分别放最小,次小及两个数字的和,没有申请多余的内存啊[/quote] 你最好下载一个VS系列的产品调试下吧 不能调试那你肯定找不到原因,你首先得知道程序是在哪崩溃的 然后再找原因
舉杯邀明月 2018-05-18
  • 打赏
  • 举报
回复
引用 18 楼 qq_40636117 的回复:
[quote=引用 15 楼 Chen8013 的回复:] [quote=引用 14 楼 zhao4zhong1 的回复:] Orz 跪谢楼上帮断帖之恩当涌泉相报!
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
// . . . . . . . .
刚好在线, 举手之劳而已,不用说得这么夸张吧。 [/quote] 谢谢大神,崩溃的概率小了很多[/quote] 你这儿应该引用14楼吧,我只是来灌水,断一下楼而已,帮你解决问题的是赵4。 
赵4老师 2018-05-18
  • 打赏
  • 举报
回复
关键加了25、26两行。
赵4老师 2018-05-18
  • 打赏
  • 举报
回复
引用 18 楼 qq_40636117 的回复:
[quote=引用 15 楼 Chen8013 的回复:] [quote=引用 14 楼 zhao4zhong1 的回复:] Orz 跪谢楼上帮断帖之恩当涌泉相报!
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
//
// . . . . . . . .
刚好在线, 举手之劳而已,不用说得这么夸张吧。 [/quote] 谢谢大神,崩溃的概率小了很多[/quote] 应该是0才对。
加载更多回复(12)

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧