zoukankan      html  css  js  c++  java
  • 算法导论 第六章 堆排序 习题6.58 k路合并排序

    /*
     * 请给出一个时间为O(nlgk),用来将k个已排序链表合并为一个排序链表的算法。
     * 此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并)
     *
     * 思路:利用有k个元素的最小堆有lgk的复杂度,
     * 所以堆的元素组成要每个链表的一个元素组成
     *
     * 具体步骤:
     *step1:取每个链表的第一个元素,构造成一个含有k个元素的堆
     *step2:把根结点的值记入排序结果中。
     *step3:判断根结点所在的链表,若该链表为空,则go to step4,否则go to step5
     *step4:删除根结点,调整堆,go to step2
     *step5:把根结点替换为原根结点所在链表中的第一个元素,调整堆,go to step 2
     */

    #include <stdio.h>
    #include <stdlib.h>

    #define PARENT(i)    (i) / 2            // parent of i
    #define LEFT(i)        (i) << 1        // left child
    #define RIGHT(i)    ((i) << 1) + 1    // right child
    #define swap(a, b, t)    { (t) = (a); (a) = (b); (b) = (t); }

    #define N        5
    #define MAXVAL    50
    #define MAXNUM    MAXVAL

    typedef struct _node {
        int                data;
        struct _node    *next;
    }Node;

    typedef Node *List;
    typedef Node HeapType;

    static List        head[N];        // N list to be combined
    static int        heap_size = 0;
    static HeapType heap[N+1];
    static int         ans[MAXNUM+1];    // finaly sorted array

    void list_init(List *L)
    {
        *L = (List)malloc(sizeof(Node));
        if (*L == NULL)
            exit(-1);
        (*L)->next = NULL;
    }

    Node *make_node(Node *a, int val)
    {
        a = (List)malloc(sizeof(Node));
        if (a == NULL)
            return NULL;

        a->data = val;
        a->next = NULL;
        return a;
    }

    /* create n lists, each list in an ascending order */
    void creat_lists(List head[], int n)
    {
        int        i, val, listno;
        Node    *tn;

        for (i = 0; i < n; i++) {
            list_init(&head[i]);
        }

        srand(time(NULL));
        for (val = MAXVAL; val > 0; val--) {
            listno = rand() % N;    // random list number
            if ( (tn = make_node(tn, val)) == NULL) {
                fprintf(stderr, "make node failed\n");
                return ;
            }
            tn->data = val;
            tn->next = head[listno]->next;
            head[listno]->next = tn;
        }
    }

    void print_list(List head)
    {
        List    p = head->next;

        for ( ; p != NULL; p = p->next)
            printf("%3d ", p->data);
        printf("\n");
    }


    /*
     * LEFT(i) and RIGHT(i) are alread min-leap
     * the heap[i] may greater than either the left or right child
     * so adjust the heap when necessary.
     */
    void min_heapify(HeapType *heap, int i)
    {
        int    l, r, smallest;
        HeapType    tmp;

        l = LEFT(i);
        r = RIGHT(i);
        
        if (l <= heap_size && heap[l].data < heap[i].data)
            smallest = l;
        else
            smallest = i;
        if (r <= heap_size && heap[r].data < heap[smallest].data)
            smallest = r;

        if (smallest != i) {
            swap(heap[i], heap[smallest], tmp);
            min_heapify(heap, smallest);
        }
    }

    /* insert a node to the min-heap */
    void min_heap_insert(HeapType *heap, int i, Node node)
    {
        while (i > 1 && heap[PARENT(i)].data > node.data) {
            heap[i] = heap[PARENT(i)];
            i = PARENT(i);
        }
        heap[i] = node;
        heap_size++;
    }

    /* remove the minmum element of the heap */
    void heap_extract_min(HeapType *heap)
    {
        int i;

        heap[1] = heap[heap_size];
        heap_size--;
        min_heapify(heap, 1);
    }

    /* sort k lists using a min-heap, runtime: O(n*lgk) */
    void heapsort_kcombine(HeapType *heap, const List  head[], int k)
    {
        int        i, listno;

        for (i = 0; i < k; i++) {
            min_heap_insert(heap, i+1, *head[i]->next);
        }

        i = 0;
        while (heap_size > 0) {
            ans[i++] = heap[1].data;
            if (heap[1].next != NULL) {  // 链表不为空
                heap[1] = *heap[1].next;
                min_heapify(heap, 1);
            } else {
                heap_extract_min(heap);
            }
        }
    }

    void print_heap(HeapType *heap)
    {
        int    i;

        for (i = 1; i <= heap_size; i++) {
            printf("%3d\n", heap[i].data);
        }
    }

    int main()
    {
        int            i;

        printf("Create %d lists as follow:\n", N);
        creat_lists(head, N);
        for (i = 0; i < N; i++) {
            printf("list %d: ", i+1);
            print_list(head[i]);
        }

        heapsort_kcombine(heap, head, N);

        printf("%d list sorted:\n", N);
        for (i = 0; i < MAXNUM; i++)
            printf("%3d%s", ans[i], (i+1) % 10 == 0 ? "\n" : " ");

        exit(0);
    }

  • 相关阅读:
    Unix/Linux笔记全集
    深入浅出-变长参数
    基于 SSH 的远程操作以及安全,快捷的数据传输<转>
    面向对象的特性—— 封装
    wpf 窗体翻页效果
    wpf控件拖动
    Wpf 导出CSV文件
    wpf 导出Excel
    Wpf Button 样式
    wpf简单进度条
  • 原文地址:https://www.cnblogs.com/huiqin/p/3674856.html
Copyright © 2011-2022 走看看