哈夫曼树

///本想着复习一下 二叉树就学哈夫曼的 呵呵哒 复习就用了一晚上 这效率也是没谁了
///都粘上。。。
/*
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 100;
int n = 0, m = 0;
typedef struct treenode
{
    char data;
    treenode *lchild;
    treenode *rchild;
}node, *Tree;
int num = 0;
node *q[100];
int head = 0;
int tail = 0;
node *createtree(node *t)
{
    char a;
    cin >> a;
    if(a == '0')
        return NULL;
    t = new node;
    t->data = a;
    t->lchild = createtree(t->lchild);
    t->rchild = createtree(t->rchild);
    return t;
}
void in_order(node *t)
{
    if(t)
    {
        in_order(t->lchild);
        cout << t->data;
        in_order(t->rchild);
    }
}
bool is_Empty()
{
    int flag = 0;
    for(int i=head; i<tail; i++)///最开始这里写的1~maxn 层序遍历之后就会崩掉
    {                                 ///因为那些出队的元素 实际上还存在在数组里 出队就是不在头和尾之间
        if(q[i] != NULL)
        {

            flag = 1;
            break;
        }
    }
    if(flag)
        return false;
    return true;
}

void level_order(node *t)
{*/
    /*if(t)
    {
        queue<node*>q;
        while(!q.empty())
            q.pop();
        q.push(t);
        while(!q.empty())
        {
            node *a = q.front();
            q.pop();
            cout << a->data;
            if(a->lchild)
                q.push(a->lchild);
            if(a->rchild)
                q.push(a->rchild);
        }
    }*/
    ///用STL习惯了 都不会数组的了
    ///数组模拟队列 是 只输出head 和tail之间的~
   /* if(t)///head 控制出队 tail控制入队  先进先出~
    {
        while(!is_Empty())
        {
            tail--;
        }
        q[tail++] = t;///根节点入队
        while(!is_Empty())
        {
            node *a = q[head];///取出队首元素
            head++;///出队
            cout << a->data;
            if(a->lchild)
                q[tail++] = a->lchild;
            if(a->rchild)
                q[tail++] = a->rchild;

        }
    }
}
int dep(node *t)
{
    int depth;
    if(t)
    {
        if(t->lchild)
        {
            dep(t->lchild);
            m++;
        }
        if(t->rchild)
        {
            dep(t->rchild);
            n++;
        }
    }
    depth = m>n?m:n;
    return depth;
}

int leaves(node *t)
{

    if(t)
    {
        if(t->lchild)
        leaves(t->lchild);
        if(t->lchild == NULL && t->rchild == NULL)
        {
            num++;
        }
        if(t->rchild)
        leaves(t->rchild);
    }

    return num;  ///这样写的结果就是输出122333   可以做个数组然后输出最后一个 但是这也太麻烦了 所以还是看正常解法吧
}///哈哈哈 果然做个返回值最直接啊 哈哈哈哈哈哈哈哈哈哈哈
bool is_Empty(node *t)
{
    if(t)///
        return false;
    return true;
}
node *point(node *t, char e)///在树里找值为e的节点
{
    ///这里就要BFS了 为了考试不挂 那就数组模拟队列吧 T^T
    if(t)
    {
         head = 0;
         tail = 0;///头尾相等就是空
         q[tail++] = t;
         while(head!=tail)
         {
             node *a = q[head];
             head++;
             if(a->data == e)
                return a;
             if(a->lchild)
                q[tail++] = a->lchild;
             if(a->rchild)
                q[tail++] = a->rchild;
         }
    }
    return NULL;
}
node *parent(node *t, char e)
{
    node *p = point(t, e);///找到e这个节点了 那么接着就是找p的双亲了
    head = 0;
    tail = 0;
    q[tail++] = t;
    while(head!=tail)
    {
        node *a = q[head];
        head++;
        if(a->lchild == p || a->rchild==p)
            return a;
        if(a->lchild)
            q[tail++] = a->lchild;
        if(a->rchild)
            q[tail++] = a->rchild;
    }
    return NULL;
}
void insert_node(node *t, node *t1, char e1, int LR)///e1是要找的节点的值
{///LR是插在哪里
    if(t)
    {
        node *p = point(t, e1);///
        if(p == NULL)
        {
            cout << "not founded" << endl;
            return;
        }
        node *tmp = p;
        if(LR == 0)
        {

            while(tmp->lchild)
            {
                tmp = tmp->lchild;
            }
            tmp->lchild = t1;
        }
        else if(LR == 1)
        {
            while(tmp->rchild)
            {
                tmp = tmp->rchild;
            }
            tmp->rchild = t1;
        }

    }
    ///node *q = parent(t, e1);

}
void delete_node(node *t1, char e, int LR)
{
    if(t1)
    {
        node *p = point(t1, e);
        if(p == NULL)
        {
            cout << "not founded" << endl;
            return;
        }
        if(LR == 0)
        {
            p->lchild = NULL;
        }
        else if(LR == 1)
        {
            p->rchild = NULL;
        }
    }

}*/
/*
node* destroy(node *t)///node 不让引用  *Tree才让引用 但是我弄返回值 把删掉的根节点返回去 应该没有问题呀
{
    if(t){
        if(t->lchild)
            destroy(t->lchild);
        if(t->rchild)
            destroy(t->rchild);
        delete t;
        t = NULL;
        return t;
    }
}
*/
/*
 void destroy(Tree &t)///node 不让引用  *Tree才让引用 但是我弄返回值 把删掉的根节点返回去 应该没有问题呀
{
    if(t){
        if(t->lchild)
            destroy(t->lchild);
        if(t->rchild)
            destroy(t->rchild);
        delete t;
        t = NULL;
    }
}*/
///下面的销毁错错错 我按左根右的顺序去删除 但是但是但是 根都被删除了 我还怎么去找右啊 所以错错错
/*
void destroy(node *t)
{
    if(t)
    {
        if(t->lchild)
        destroy(t->lchild);
        cout << "1" << endl;
       /// t = NULL;
        delete t;
        if(t->rchild)
        destroy(t->rchild);
    }
}*/
/*
int main()
{
    ///int a[100] = {8, 2 , 7, 89, 3, 62, 23, 15, 4, 10};
    node *tree, *t1;
    tree = new node;
    tree->lchild = NULL;
    tree->rchild = NULL;
    t1 = new node;
    t1->lchild = NULL;
    t1->rchild = NULL;
    tree = createtree(tree);
    cout << "in_order" << endl;
    in_order(tree);
    cout << endl;
    t1 = createtree(t1);
    cout << "level_order" << endl;
    level_order(t1);
    cout << endl;
    cout << "the depth is" << endl;
    int depth = dep(t1);
    cout << depth << endl;
    cout << "the leaves are" << endl;
    int num = leaves(t1);
    cout << num;
    cout << endl;
    cout << "find e" << endl;
    node *p = point(t1,'d');
    cout << "find parent" << endl;
    node *q = parent(t1, 'a');
    if(q)
    cout << q->data << endl;
    else
        cout << "NULL" << endl;
    if(p)
        cout << p->data << endl;
    else
        cout << "not founded" << endl;
    cout << "insert node:" << endl;
    insert_node(t1, tree, 'c', 1);
    cout << "after insert(level_order):" << endl;
    level_order(t1);

    cout << "delete node:" << endl;
    delete_node(t1, 'a', 0);
    level_order(t1);
    cout << endl;
    destroy(t1);
    if(t1)
        cout << "No" << endl;///这里留下 做个对比吧 我以为会输出Yes呢 结果却是No
    else
        cout << "Yes" << endl;
    if(is_Empty(t1))
        cout << "YES" << endl;///这里是YES  呵呵哒 忘传参了 这里也是NO 我的销毁操作根本没起作用 呵呵呵呵哒
    else
        cout << "NO" << endl;
    return 0;
}
*/
/*
abe00f00cd000
*/
/*
#include<iostream>
#include<queue>
using namespace std;
typedef struct treenode
{
    int data;
    treenode *lchild;
    treenode *rchild;
}node, *Tree;
node *q[100];
int head, tail;
int flag = 0;
int arr[15] = {4, 17, 2, 67, 15, 7, 13, 9, 19, 10};
void insert_node(node *t, node *child)
{
    if(t)
    {
        if(t->lchild && t->data >= child->data)
        {
            insert_node(t->lchild, child);
        }
        if(t->rchild && t->data < child->data)
        {
            insert_node(t->rchild, child);
        }
        if(t->lchild == NULL && child->data <= t->data)
        {
            t->lchild = child;
        }
        else if(t->rchild == NULL && child->data > t->data)
            t->rchild = child;
    }
}
void create_node(Tree &t)///建树啊 删树啊 都得用引用 建树返回值也行 删树我没返回明白呢
{
    node *child;
    t = new node;
    t->data = arr[0];
    t->rchild = NULL;
    t->lchild = NULL;
    for(int i=1; i<10; i++)
    {
        child = new node;
        child->lchild = NULL;
        child->rchild = NULL;
        child->data = arr[i];
        insert_node(t, child);
    }
}
void in_order(node *t)
{
    if(t)
    {
        if(t->lchild)
            in_order(t->lchild);
        cout << t->data << ' ';
        if(t->rchild)
            in_order(t->rchild);

    }
}

void level_order(node *t)
{
    if(t)
    {
        head = 0;
        tail = 0;
        q[tail++] = t;
        while(head!=tail)
        {
            node *a = q[head];
            head++;
            cout << a->data << ' ';
            if(a->lchild)
                q[tail++] = a->lchild;
            if(a->rchild)
                q[tail++] = a->rchild;
        }
    }
}
node *point(node *t, int e)
{
    if(t)
    {
        head = 0;
        tail = 0;
        q[tail++] = t;
        while(head!=tail)
        {
            node *a = q[head];
            head++;
            if(a->data == e)
                return a;
            if(a->lchild)
                q[tail++] = a->lchild;
            if(a->rchild)
                q[tail++] = a->rchild;
        }
    }
    return NULL;
}
node *parent(node *t, node *p)
{
    if(t)
    {
        head = 0;
        tail = 0;
        q[tail++] = t;
        while(head!=tail)
        {
            node *a = q[head];
            head++;
            if(a && a->lchild == p)
            {
                flag = 0;
                return a;
            }

            if(a && a->rchild == p)
            {
                flag = 1;
                return a;
            }
            if(a->lchild)
                q[tail++] = a->lchild;
            if(a->rchild)
                q[tail++] = a->rchild;
        }
    }
    return NULL;
}
void delete_node(Tree &t, int e)
{
    if(t)
    {
        node *p = point(t, e);
        if(p == NULL)///1.空
        {
            cout << "not founded" << endl;
            return;
        }
        node *q = parent(t, p);
        ///2.有父节点 没有左右孩子
        if(q && p->lchild == NULL && p->rchild == NULL)
        {
            if(flag == 0)
            {
                q->lchild = NULL;
                delete p;
            }
            else if(flag == 1)
            {
                q->rchild = NULL;
                delete p;

            }
        }
        ///3.有父节点 有左孩子 没右孩子
        else if(q && p->lchild && p->rchild==NULL)
        {
            if(flag == 0)
            {
                q->lchild = p->lchild;
                delete p;
            }
            else if(flag == 1)
            {
                q->rchild = p->lchild;
                delete p;
            }
        }
        ///4.有父节点 没左孩子 有右孩子
        else if(q && p->lchild == NULL && p->rchild)
        {
            if(flag == 0)
            {
                q->lchild = p->rchild;
                delete p;
            }
            else if(flag == 1)
            {
                q->rchild = p->rchild;
                delete p;
            }
        }
        ///5.有父节点 有左右孩子   假定左孩子放到原来的右节点上 右节点放左孩子上
        else if(q && p->lchild && p->rchild)///那左孩子的左右节点怎么办呢 不能丢 就找地儿随便放得了
        {
            if(flag == 0)
            {
                q->lchild = p->lchild;


                if(p->lchild->lchild && p->lchild->rchild)
                {
                    node *tmp = p->lchild->lchild;
                    while(!tmp)
                    {
                        tmp = tmp->lchild;
                    }
                    tmp->lchild = p->lchild->rchild;
                }
                else if(p->lchild->lchild == NULL && p->lchild->rchild)
                    p->lchild->lchild = p->lchild->rchild;
                else if(p->lchild->rchild == NULL && p->lchild->lchild)
                    p->lchild->rchild = p->lchild->lchild;
                q->lchild->rchild = p->rchild;
                delete p;
            }
            else if(flag == 1)
            {
                q->rchild = p->lchild;
                if(p->lchild->lchild != NULL && p->lchild->rchild)
                {
                    node *tmp = p->lchild->lchild;
                    while(!tmp)
                    {
                        tmp = tmp->lchild;
                    }
                    tmp->lchild = p->lchild->rchild;
                }
                else if(p->lchild->lchild == NULL && p->lchild->rchild)
                    p->lchild->lchild = p->lchild->rchild;
                else if(p->lchild->rchild == NULL && p->lchild->lchild)
                    p->lchild->rchild = p->lchild->lchild;
                q->rchild->rchild = p->rchild;
                delete p;
            }
        }
        ///6.没父节点 没左右孩子
        else if(q==NULL && p->rchild == NULL && p->lchild == NULL)
        {
            t = NULL;///第一次忘写了 我们并没有销毁树
            delete p;
        }
        ///7.没父节点 有左孩子 没右孩子
        else if(q==NULL && p->lchild && p->rchild == NULL)
        {
            t = p->lchild;
            delete p;
        }
        ///8.没父节点 没左孩子 有右孩子
        else if(q==NULL && p->rchild && p->lchild == NULL)
        {
            t = p->rchild;
            delete p;
        }
        ///9.没父节点 有左右孩子   假定左孩子上位
        else if(q==NULL && p->lchild && p->rchild)
        {///
            /*t->rchild = p->rchild;*/ /// 真搞笑 这相当于没操作啊
          /*  node *tmp;
            tmp = p;
            t = p->lchild;
            t->rchild = p->rchild;
            delete p;
        }

    }
}
bool is_Empty(node *t)
{
    if(t)
        return false;
    return true;
}
void destroy(Tree &t)
{
    if(t)
    {
        destroy(t->lchild);
        destroy(t->rchild);
        t = NULL;
        delete t;
    }
}
int main()
{
    node *t1, *t2;
    create_node(t1);
    cout << "in_order:" << endl;
    in_order(t1);
    cout << endl;
    cout << "level_order :" << endl;
    level_order(t1);
    cout << endl;
    cout << "insert a node:" << endl;
    int n;
    cin >> n;
    node *p;
     p = new node;
     p->lchild = NULL;///
     p->rchild = NULL;
    p->data = n;
    insert_node(t1, p);
    cout << "level_order: " << endl;
    level_order(t1);///后面什么都不写的话 那黑框框直接就消失了 我好方啊
    cout << endl;
    cout << "delete node :" << endl;
    int s;
    while(1)
    {
        cin >> s;
        delete_node(t1, s);
        cout << "level order is" << endl;
        level_order(t1);
        cout << endl;
        if(t1 == NULL)
            cout << "NULL" << endl;

    }

    destroy(t1);
    if(is_Empty(t1))
    {
        cout << "empty!" << endl;
    }
    if(t1 == NULL)
    cout << "NULL" << endl;
    cin >> s;
    return 0;
}*/


///这次写又遇到了不少问题 又用了一晚上 本来以为很快就能写完的 可是老遇到BUG 不过我很享受这个过程
///用着瑞瑞的电脑 瑞瑞的机械键盘 感觉好爽啊 哈哈哈哈
/*
in_order:
2 4 7 9 10 13 15 17 19 67
level_order :
4 2 17 15 67 7 19 13 9 10
insert a node:
1
level_order:
4 2 17 1 15 67 7 19 13 9 10
delete node :
2
level order is
4 1 17 15 67 7 19 13 9 10
15
level order is
4 1 17 7 67 13 19 9 10
17
level order is
4 1 7 13 67 9 19 10
67
level order is
4 1 7 13 19 9 10
4
level order is
1 7 13 19 9 10
13
level order is
1 7 9 19 10
19
level order is
1 7 9 10
7
level order is
1 9 10
9
level order is
1 10
10
level order is
1
1
level order is

NULL

*/

///这个挺好玩 要多大就分配多大 不浪费空间
///伪代码
/*
int main()
{
    int n;
    int *a;
    while(1)
    {
        scanf("%d", &n);
        if(n>1)
            break;
        else
            printf("请重新输入\n");
    }
    a = malloc(sizeof(n*int));
}*/
#include<iostream>
using namespace std;

typedef struct treenode
{
    int data;
    treenode *lchild;
    treenode *rchild;
}node, *Tree;

int a[100];
void print(node *t)///先序遍历
{
    if(t)
    {
        cout << t->data;
        if(t->lchild || t->rchild)
        {
            cout << "(" ;
            if(t->lchild)
               print(t->lchild);
            if(t->rchild)
            {
                cout << ",";
                print(t->rchild);
            }
            cout << ")";
        }

    }
}
node *createHuffmantree(int n)
{
    node *b[100], *q;
    for(int i=0; i<n; i++)///初始化b指针数组,使每个指针元素指向a数组中对应的元素结点
    {
        b[i] = new node;
        b[i]->data = a[i];
        b[i]->lchild = b[i]->rchild = NULL;
    }
    for(int i=0; i<n-1; i++)///循环n-1次 建立哈夫曼树
    {
        ///k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
        int k1 = -1, k2;
        for(int j=0; j<n; j++)///让k1初始指向森林中第一棵树,k2指向第二棵
        {
            if(k1 == -1 && b[j])
            {
                k1 = j;
                cout << k1 << endl;
                continue;
            }
            if(b[j])
            {
                k2 = j;
                cout << k2 << endl;
                break;
            }///我觉得k1 永远是0, k2 永远是1  呵呵哒 你错了
        }
        for(int j=k2; j<n; j++)
        {
            if(b[j])///第一次 比较b[k2]->data 与b[k1]->data  小的为k1。。。
            {
                if(b[j]->data < b[k1]->data)
                {
                    k2 = k1;///因为本来k1是最小的 现在找到比k1小的了 那次小的就是k1
                    k1 = j;
                }
                else if(b[j]->data < b[k2]->data)
                {
                    k2 = j;
                }
            }
        }///最小的和次小的节点寻找完毕 可惜我道行尚浅 竟然没看出这是什么排序 T^T 又要复习排序了
        q = new node;///计算新节点
        q->data = b[k1]->data + b[k2]->data;
        q->lchild = b[k1];
        q->rchild = b[k2];

        b[k1] = q;///那就是下一步要形成的树左子树为q, 右子树为空
        b[k2] = NULL;///次优的置空
        ///那接下来 森林就是最优 次优结合体 与 其他的小叶子 重复以上步骤 ~~~
        ///分析完毕 抽抽抽抽风风风风

    }
    delete []b;
    return q;
}

int weight_path_length(node *t, int len)
{
    if(t)
    {
        if(t->lchild == NULL && t->rchild == NULL)
        {
            return t->data * len;
        }
        else
        {
            return weight_path_length(t->lchild, len+1)+weight_path_length(t->rchild, len+1);
        }
    }
    return 0;
}
void HuffmanCode(node *t, int len)///后序遍历的顺序
{
    static int a[10];
    if(t)
    {
        if(t->lchild == NULL && t->rchild == NULL)
        {
            for(int i=0; i<len; i++)
                cout << a[i];
            cout << endl;
        }
        else
        {
            a[len] = 0;
            HuffmanCode(t->lchild, len+1);
            a[len] = 1;
            HuffmanCode(t->rchild, len+1);
        }
    }
}

int main()
{
   int n;
   cin >> n;
   for(int i=0; i<n; i++)
        cin >> a[i];
    node *tree = createHuffmantree(n);
    cout << "广义表形式的哈夫曼树:" << endl;
    print(tree);
    cout << endl;
    cout << "哈夫曼树的带权路径长度:" << endl;
    cout << weight_path_length(tree, 0) << endl;
    cout << "每个叶子节点的哈夫曼编码:" << endl;
    HuffmanCode(tree, 0);
    cout << endl;
    for(int i=0; i<n; i++)
        cout << a[i];/// 4 2 1 3 
    return 0;
}
/*
4
4 2 1 3
0
1
0
2
0
2
广义表形式的哈夫曼树:
10(4,6(3(1,2),3))
哈夫曼树的带权路径长度:
19
每个叶子节点的哈夫曼编码:
0
100
101
11


Process returned 0 (0x0)   execution time : 10.987 s
Press any key to continue.

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值