Cod sursa(job #1061034)

Utilizator impulseBagu Alexandru impulse Data 19 decembrie 2013 03:44:29
Problema Coduri Huffman Scor 65
Compilator c Status done
Runda Arhiva educationala Marime 3.38 kb
//
//  main.c
//  huffman
//
//  Created by Alexandru Bâgu on 12/18/13.
//  Copyright (c) 2013 Alexandru Bâgu. All rights reserved.
//

#include <stdio.h>

#define MAX_N 1000001
#define INF 0x7FFFFFFF

typedef unsigned long long ulong;

typedef struct {
    int digits;
    ulong value;
} huffman;
typedef struct nodeStr {
    ulong value;
    int ind;
    struct nodeStr *left, *right;
} node;

typedef struct _heapStr {
    int size;
    node *nodes;
} *heap, heapStr;

int swap(node* n, node* m)
{
    node p = *n;
    *n = *m;
    *m = p;
    return 0;
}

int up(heap h, int pos)
{
    while(pos != 1 && h->nodes[pos].value < h->nodes[pos / 2].value)
    {
        swap(h->nodes + pos, h->nodes + pos / 2);
        pos /= 2;
    }
    return 0;
}

int down(heap h, int pos)
{
    while(h->size >= 2 * pos)
    {
        int c1 = pos * 2, c2 = c1 + 1;
        if(h->size >= c2)
            if(h->nodes[c1].value > h->nodes[c2].value)
                c1 = c2;
        
        if(h->nodes[pos].value > h->nodes[c1].value)
        {
            swap(h->nodes + pos, h->nodes + c1);
            pos = c1;
        }
        else
            pos = h->size;
    }
    return 0;
}

int add(heap h, node* node)
{
    h->nodes[++h->size] = *node;
    up(h, h->size);
    return 0;
}

node* rem(heap h, int pos)
{
    node* n = malloc(sizeof(node));
    *n = h->nodes[pos];
    h->nodes[pos] = h->nodes[h->size--];
    //up(h, pos);
    down(h, pos);
    return n;
}

node* paste(node* n, node* m)
{
    node* mix = malloc(sizeof(node));
    mix->value = n->value + m->value;
    mix->left = n;
    mix->right = m;
    return mix;
}

int print(heap h)
{
    int k = 1, j = 1, i;
    for(i = 1; i <= h->size; i++)
    {
        printf("%d", h->nodes[i].value);
        if(h->nodes[i].left != NULL)
            printf("!");
        if(h->nodes[i].right != NULL)
            printf("!");
        printf("  ");
        k--;
        if(k == 0)
        {
            k = 1 << j;
            j++;
            printf("\n");
        }
    }
    printf("\n");
    return 0;
}

ulong build_list(node* h, ulong value, int digits, huffman *huff)
{
    ulong sum = 0;
    if(h->left == NULL && h->right == NULL)
    {
        huff[h->ind].digits = digits;
        huff[h->ind].value = value;
    }
    else
    {
        sum = h->value;
    }
    if(h->left != NULL)
        sum += build_list(h->left, value << 1, digits + 1, huff);
    if(h->right != NULL)
        sum += build_list(h->right, (value << 1) | 1 , digits + 1, huff);
    return sum;
}


int main(int argc, const char * argv[])
{
    int i;
    freopen("huffman.in", "r", stdin);
    freopen("huffman.out", "w", stdout);
    int n;
    scanf("%d", &n);
  
    huffman *huff = (huffman*) malloc((n+1) * sizeof(huffman));
    heap heap = (heapStr*) malloc(sizeof(heapStr));
    heap->nodes = (node*) malloc((n+2) * sizeof(node));
    for(i = 0; i <= n; i++) heap->nodes[i].value = INF;
    
    heap->size = n;
    for(i = 1; i <= heap->size; i++) {
        scanf("%llu", &heap->nodes[i].value);
        heap->nodes[i].ind = i;
    }
    while(heap->size > 1)
    {
        node *min1 = rem(heap, 1);
        node *min2 = rem(heap, 1);
        node* mix = paste(min1, min2);
        add(heap, mix);
    }
    node node = heap->nodes[1];
    ulong sum = build_list(&node, 0, 0, huff);
    printf("%llu\n", sum);
    for(i = 1; i <= n; i++)
        printf("%d %llu\n", huff[i].digits, huff[i].value);
    return 0;
}