贪婪算法

最小生成树(Kruskal’s Minimum Spanning Tree)

#include <cstdio>
#include <cstdlib>
#include <cstring>

typedef struct
{
    int src, dest, weight;
}Edge;

typedef struct
{
    int vertices, edges_n;
    Edge *edges;
}Graph;

typedef struct
{
    int parent;
    int rank;
}Subset;

Graph * createGraph(int vertices, int edges);
int compare(const void *a, const void *b);
int find(Subset *subsets, int n);
void Union(Subset *subsets, int x, int y);
void KruskalMST(Graph *graph);

int main(void)
{
    /* Let us create following weighted graph
        10
    0--------1
    |  \     |
   6|   5\   |15
    |      \ |
    2--------3
        4
    */
    int vertices = 4;
    int edges_n = 5;
    Graph *graph = createGraph(vertices, edges_n);

    // add edge 0-1
    graph->edges[0].src = 0;
    graph->edges[0].dest = 1;
    graph->edges[0].weight = 10;

    // add edge 0-2
    graph->edges[1].src = 0;
    graph->edges[1].dest = 2;
    graph->edges[1].weight = 6;

    // add edge 0-3
    graph->edges[2].src = 0;
    graph->edges[2].dest = 3;
    graph->edges[2].weight = 5;

    // add edge 1-3
    graph->edges[3].src = 1;
    graph->edges[3].dest = 3;
    graph->edges[3].weight = 15;

    // add edge 2-3
    graph->edges[4].src = 2;
    graph->edges[4].dest = 3;
    graph->edges[4].weight = 4;

    KruskalMST(graph);

    system("pause");
    return 0;
}

Graph * createGraph(int vertices, int edges)
{
    Graph *graph = (Graph *)calloc(1, sizeof(Graph));
    graph->vertices = vertices;
    graph->edges_n = edges;
    graph->edges = (Edge *)calloc(edges, sizeof(Edge));

    return graph;
}

int compare(const void * a, const void * b)
{
    return ((Edge *)a)->weight > ((Edge *)b)->weight;
}

/*
    Find the root of which subset a particular element is in.
    Using path compression for optimization.
*/
int find(Subset * subsets, int n)
{
    if (subsets[n].parent != n)
    {
        subsets[n].parent = find(subsets, subsets[n].parent);
    }

    return subsets[n].parent;
}

/*
    Join two subsets into a single subset.
    Uion by rank for optimization.
*/
void Union(Subset * subsets, int x, int y)
{
    int x_root = find(subsets, x);
    int y_root = find(subsets, y);

    if (subsets[x_root].rank < subsets[y_root].rank)
        subsets[x_root].parent = y_root;
    else if (subsets[x_root].rank > subsets[y_root].rank)
        subsets[y_root].parent = x_root;
    else
    {
        subsets[y_root].parent = x_root;
        subsets[x_root].rank++;
    }
}

/*
    Using Kruskal's algorithm to find MST in the connected and undirected graph
*/
void KruskalMST(Graph * graph)
{
    int vertices = graph->vertices;
    Subset *subsets;

    subsets = (Subset *)calloc(vertices, sizeof(Subset));
    for (int i = 0; i < vertices; i++)
    {
        subsets[i].parent = i;
    }

    qsort(graph->edges, graph->edges_n, sizeof(Edge), compare);

    int e = 0, i = 0;
    Edge *result;

    result = (Edge *)calloc(vertices - 1, sizeof(Edge));
    while (e < vertices - 1)
    {
        Edge next_edge = graph->edges[i++];

        int x = find(subsets, next_edge.src);
        int y = find(subsets, next_edge.dest);

        if (x != y)
        {
            result[e++] = next_edge;
            Union(subsets, x, y);
        }
    }

    printf("Edges in the constructed MST\n");
    for (int i = 0; i < vertices - 1; i++)
    {
        printf("%d -- %d == %d\n", result[i].src, result[i].dest, result[i].weight);
    }

    return;
}

 

最小生成树(Prim’s Minimum Spanning Tree)

#include <cstdio>
#include <cstdlib>

int minKey(int *key, bool *mst_set, int vertices);
void primMST(int **graph, int vertices);
void printMST(int *parent, int **graph, int vertices);

int main(void)
{
/* Let us create the following graph
      2    3
   (0)--(1)--(2)
    |   / \   |
   6| 8/   \5 |7
    | /     \ |
   (3)-------(4)
         9          
*/
    int vertices = 5;
    int **graph = NULL;
    int array[] = { 0, 2, 0, 6, 0, 2, 0, 3, 8, 5, 0, 3, 0, 0, 7, 6, 8, 0, 0, 9, 0, 5, 7, 9, 0 };

    graph = (int **)calloc(vertices, sizeof(int *));
    for (int i = 0; i < vertices; i++)
    {
        graph[i] = (int *)calloc(vertices, sizeof(int));
    }

    int k = 0;
    for (int i = 0; i < vertices; i++)
    {
        for (int j = 0; j < vertices; j++)
        {
            graph[i][j] = array[k++];
        }
    }

    primMST(graph, vertices);

    system("pause");
    return 0;
}

int minKey(int * key, bool * mst_set, int vertices)
{
    int min = INT_MAX;
    int min_index;

    for (int i = 0; i < vertices; i++)
    {
        if (!mst_set[i] && key[i] < min)
        {
            min = key[i];
            min_index = i;
        }
    }

    return min_index;
}

void primMST(int ** graph, int vertices)
{
    int *parent, *key;
    bool *mst_set;

    parent = key = NULL;
    mst_set = NULL;
    parent = (int *)calloc(vertices, sizeof(int));
    key = (int *)calloc(vertices, sizeof(int));
    mst_set = (bool *)calloc(vertices, sizeof(bool));

    for (int i = 0; i < vertices; i++)
    {
        key[i] = INT_MAX;
    }
    key[0] = 0;
    parent[0] = -1;

    for (int i = 0; i < vertices - 1; i++)
    {
        int n = minKey(key, mst_set, vertices);
        mst_set[n] = true;

        for (int j = 0; j < vertices; j++)
        {
            if (graph[n][j] && !mst_set[j] && graph[n][j] < key[j])
            {
                key[j] = graph[n][j];
                parent[j] = n;
            }
        }
    }

    printMST(parent, graph, vertices);
}

void printMST(int * parent, int ** graph, int vertices)
{
    printf("edge\tweight\n");
    for (int i = 1; i < vertices; i++)
    {
        printf("%d - %d\t%d\n", parent[i], i, graph[parent[i]][i]);
    }
}

 


 

霍夫曼编码(Huffman Coding)

#include <cstdio>
#include <cstdlib>

/* A Huffman tree node */
typedef struct MinHeapNode
{
    char data;
    int frequency;
    struct MinHeapNode *left, *right;
}MinHeapNode;

/* A Min Heap */
typedef struct
{
    int size;
    int capacity;
    MinHeapNode **array;
}MinHeap;

MinHeap * createMinHeap(int capacity);
MinHeapNode * newNode(char data, int frequency);
void swapMinHeapNode(MinHeapNode **a, MinHeapNode **b);
void minHeapify(MinHeap *min_heap, int key);
MinHeap * buildMinHeap(char *data, int *frequency, int size);
MinHeapNode *extractMin(MinHeap *min_heap);
void insertMinHeap(MinHeap *min_heap, MinHeapNode *min_heap_node);

MinHeapNode * buildHuffmanTree(char *data, int *frequency, int size);
void huffmanCoding(char *data, int *frequency, int size);
void printCodes(MinHeapNode *root, char *codes, int depth);

int main(void)
{
    int n = 6;
    char array[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
    int frequency[] = { 5, 9, 12, 13, 16, 45 };

    huffmanCoding(array, frequency, n);

    system("pause");
    return 0;
}
/* Create a min heap whose size is zero */
MinHeap * createMinHeap(int capacity)
{
    MinHeap *min_heap = (MinHeap *)calloc(1, sizeof(MinHeap));
    min_heap->size = 0;
    min_heap->capacity = capacity;
    min_heap->array = (MinHeapNode **)calloc(capacity, sizeof(MinHeapNode *));

    return min_heap;
}

MinHeapNode * newNode(char data, int frequency)
{
    MinHeapNode *node = (MinHeapNode *)calloc(1, sizeof(MinHeapNode));
    node->left = node->right = NULL;
    node->data = data;
    node->frequency = frequency;

    return node;
}

void swapMinHeapNode(MinHeapNode ** a, MinHeapNode ** b)
{
    MinHeapNode *temp = *a;
    *a = *b;
    *b = temp;
}

void minHeapify(MinHeap * min_heap, int key)
{
    int left = (key << 1) + 1;
    int right = (key << 1) + 2;
    int smallest = key;

    if (left < min_heap->size && min_heap->array[left]->frequency < min_heap->array[smallest]->frequency)
        smallest = left;

    if (right < min_heap->size && min_heap->array[right]->frequency < min_heap->array[smallest]->frequency)
        smallest = right;

    if (smallest != key)
    {
        swapMinHeapNode(&min_heap->array[key], &min_heap->array[smallest]);
        minHeapify(min_heap, smallest);
    }
}

MinHeap * buildMinHeap(char * data, int * frequency, int size)
{
    MinHeap *min_heap = createMinHeap(size);

    for (int i = 0; i < size; i++)
    {
        min_heap->array[i] = newNode(data[i], frequency[i]);
    }
    min_heap->size = size;

    for (int i = (size >> 1) - 1; i >= 0; i--)
    {
        minHeapify(min_heap, i);
    }

    return min_heap;
}

MinHeapNode * extractMin(MinHeap * min_heap)
{
    MinHeapNode *min = min_heap->array[0];
    min_heap->array[0] = min_heap->array[min_heap->size - 1];
    min_heap->size--;
    minHeapify(min_heap, 0);

    return min;
}

void insertMinHeap(MinHeap * min_heap, MinHeapNode * min_heap_node)
{
    int i = min_heap->size;
    min_heap->size++;

    while (i && min_heap_node->frequency < min_heap->array[(i - 1) >> 1]->frequency)
    {
        min_heap->array[i] = min_heap->array[(i - 1) >> 1];
        i = (i - 1) >> 1;
    }
    min_heap->array[i] = min_heap_node;
}

MinHeapNode * buildHuffmanTree(char * data, int * frequency, int size)
{
    MinHeap *min_heap = buildMinHeap(data, frequency, size);

    MinHeapNode *left, *right, *top;
    while (min_heap->size != 1)
    {
        left = extractMin(min_heap);
        right = extractMin(min_heap);

        top = newNode('$', left->frequency + right->frequency);
        top->left = left;
        top->right = right;
        insertMinHeap(min_heap, top);
    }

    return extractMin(min_heap);
}

void huffmanCoding(char * data, int * frequency, int size)
{
    MinHeapNode *root = buildHuffmanTree(data, frequency, size);

    char codes[100] = { 0 };
    printCodes(root, codes, 0);
}

void printCodes(MinHeapNode * root, char * codes, int depth)
{
    if (root->left)
    {
        codes[depth] = '0';
        printCodes(root->left, codes, depth + 1);
    }

    if (root->right)
    {
        codes[depth] = '1';
        printCodes(root->right, codes, depth + 1);
    }

    if (!(root->left) && !(root->right))
    {
        printf("%c: ", root->data);
        for (int i = 0; i <= depth; i++)
        {
            printf("%c", codes[i]);
        }
        printf("\n");
    }
}

 

posted @ 2017-03-22 20:08  Lao-zi  阅读(250)  评论(0)    收藏  举报