归来的哈基米树(哈夫曼树)

//老师教的一种思路,但楼主写出来后并没有完全通过PTA一道题上的测试,也许是哪里的问题楼主没注意到,暂且记录

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<stdafx.h>
#include<iostream>

#include<cstring>
using namespace std;
typedef int Elemtype;
typedef struct hajishu* manbo;
int maxd = 1000;
struct hajishu
{
    int name=0;//该节点的名称
    Elemtype data=-1;//当前节点的数据
    int left = 0, right = 0;//该节点的左右子树的名称,为0代表没有
    int parent = 0;//该节点的父母辈的名称
};

int main()
{
    hajishu H[maxd];
    int count = 0, i = 1;
    cin >> count;

    while (i <= count)//从1开始保存几位树
    {
        cin>>H[i].data;
        H[i].name = i;
        i++;
    }
    /*
    i=1;
    while (i <= count)//
    {
        printf("name%d data%d zuo%d you%d fumu%d\n", H[i].name, H[i].data, H[i].left, H[i].right, H[i].parent);
        i++;
    }
    */
    //两个指针找当前没有父母的结点最小值
    manbo top1 = &H[1];
    manbo top2 = &H[2];
    //printf("hajimi");
    int ii = 0;
    //int a = 0;//这个本来是防止死循环的,测试时循环条件是a<20
    while (1)
    {
        //a++;
        ii = 1;

        //找两个结点权重最小的而且不能有父母
        while (ii <= count)//从头到尾
        {
            if (top1->data > H[ii].data && H[ii].name != top2->name && H[ii].parent == 0)
            {
                top1 = &H[ii];
            }
            ii++;
        }
        ii = 1;
        while (ii <= count)
        {
            if (top2->data > H[ii].data && top1->name != H[ii].name && H[ii].parent == 0)
            {
                top2 = &H[ii];
            }
            ii++;
        }
        //找两个结点权重最小的

        //新建结点,这两个最小的有父母的,父母的权重是他们的权重合
        H[ii].data = top1->data + top2->data;
        H[ii].name = ii;
        top1->parent = ii;
        top2->parent = ii;
        H[ii].left = top1->name;
        H[ii].right = top2->name;

        count++;//树的最大值修改
        ii = 1;
        while (H[ii].parent != 0 && ii <= count)
        {//修改两个指针的初始位置,跳过有父母的结点,找第一个没有父母的结点
        //因为最后可能指针指向的是最末尾的,第二次循环就可能找不到
            ii++;
        }

        if (ii > count)
        {
            break;
        }
        top1 = &H[ii];//修改成功
        ii++;//top2的寻找要从下一位开始

        while (H[ii].parent != 0 && ii <= count)
        {
            ii++;
        }
        if (ii > count)//如果找出去了都找不到,那么此时只剩一个节点了,他一定是最上面的结点
        {
            break;
        }
        top2 = &H[ii];
    }
    
    i = 1;
    int sum = 0;
    while (i<=(count+1)/2)//计算这个树的WPL,只需要管叶结点即可,i<=叶节点数
    {//所有生成的新结点数=原结点*2-1
        top1 = &H[i];
        int num=0;//num代表楼层
        while (top1->parent!= 0)
        {
            top1 = &H[top1->parent];
            num++;
        }
        sum += H[i].data * num;//当前节点权重*楼层数
        i++;//下一节点
    }
    printf("%d\n", sum);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值