Cod sursa(job #1061031)

Utilizator impulseBagu Alexandru impulse Data 19 decembrie 2013 03:11:08
Problema Coduri Huffman Scor 10
Compilator c Status done
Runda Arhiva educationala Marime 3.67 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 {
    int 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)
{
    int p = pos / 2, c = (pos / 2) * 2;
    if(p == 0) return 0;
    do
    {
        if(h->nodes[p].value > h->nodes[c].value)
            swap(h->nodes + p, h->nodes + c);
        else if(h->nodes[p].value > h->nodes[c + 1].value)
            swap(h->nodes + p, h->nodes + c + 1);
    
        p /= 2;
        c = p * 2;
    }
    while(p > 0 && !(h->nodes[p].value < h->nodes[c].value || h->nodes[p].value < h->nodes[c].value));
    return 0;
}

int down(heap h, int pos)
{
    int c1, c2;
    c2 = (c1 = pos * 2) + 1;
    if(h->size < c1) return 0;
    do
    {
        if(h->size >= c2)
            if(h->nodes[c1].value > h->nodes[c2].value)
                c1 = c2;
        
        if(h->nodes[pos].value < h->nodes[c1].value)
            break;
        
        swap(h->nodes + pos, h->nodes + c1);
        
        pos = c1;
        c2 = (c1 = pos * 2) + 1;
    } while (h->size > c1);
    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("!");
        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);
    huffman *huff = (huffman*) malloc(MAX_N * sizeof(huffman));
    heap heap = (heapStr*) malloc(sizeof(heapStr));
    heap->nodes = (node*) malloc((MAX_N + 1) * sizeof(node));
    for(i = 0; i < MAX_N; i++) heap->nodes[i].value = INF;
    int n;
    scanf("%d", &n);
    heap->size = n;
    for(i = 1; i <= heap->size; i++) {
        scanf("%d", &heap->nodes[i].value);
        heap->nodes[i].ind = i;
    }
    while(heap->size > 1)
    {
        node *min1 = rem(heap, 1),
             *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;
}