算法导论6.5-8习题解答(最小堆K路合并)

来源:互联网 发布:淘宝2017双11销售额 编辑:程序博客网 时间:2024/05/21 14:53

《算法导论》第六章第五节的第8题,原题为:请给出一个时间为O(nlgk)、用来将k个已排序链表合并为一个排序链表的算法。此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并)。

算法思想:
1.
k个链表中取出每个链表的第一个元素,组成一个大小为k的数组arr,然后将数组arr转换为最小堆,那么arr[0]就为最小元素了

2.
取出arr[0],将其放到新的链表中,然后将arr[0]元素在原链表中的下一个元素补到arr[0]处,即arr[0].next,如果 arr[0].next为空,即它所在的链表的元素已经取完了,那么将堆的最后一个元素补到arr[0]处,堆的大小自动减一,循环n-k次即可。

为了方便粘贴,把.h.cpp都弄在一起,首先是两个类ListNode,然后就是两个关于最小堆操作的函数,代码有点长,但是一点都不难,因为你肯定看过最大堆的操作,那么最小堆就大同小异了:
 

#include <iostream>

usingnamespace std;

class Node

{

public:

   Node* next;

   int data;

   Node();

   Node(int d);

   operator Node()const;

   //只需用到"<"

   booloperator < (const Node& temp);

};

class List

{

public:

   Node* first;

   List();

   void insert(int d);

};

//修正i的位置,在此处已经假设i的子节点都是堆

void min_heapify(Node* &a,int i,int length);

//建立数组的堆

void build_min_heap(Node* &a,int length);

int main()

{

   int K =5;

   List* list_one  = new List();

   List* list_two = new List();

   List* list_three = new List();

   List* list_four = new List();

   List* list_five = new List();

   for(int i =0; i <5; i++)

   {

       list_one->insert(i);

       list_two->insert(i - 3);

       list_three->insert(i + 5);

       list_four->insert(2*i);

       list_five->insert(i - 10);

   }

   Node* arr = new Node[K];

   arr[0] = *(list_one->first);

   arr[1] = *(list_two->first);

   arr[2] = *(list_three->first);

   arr[3] = *(list_four->first);

   arr[4] = *(list_five->first);

   //先对这K个排序

   build_min_heap(arr, K);

   List* list = new List();

   //每次取arr[0]的下一个Node,如果Node为空的话,

   //则把堆末尾的元素补到arr[0],由于有--K,所以堆的大小减一

   while(K >0)

   {

       list->insert(arr[0].data);

       if(arr[0].next != NULL)

           arr[0] = *(arr[0].next);

       else

           arr[0] = arr[--K];

       min_heapify(arr, 0, K);

   }

   Node* begin = list->first;

   while(begin != NULL)

   {

       cout<<begin->data<<endl;

       begin = begin->next;

   }

   return0;

}

void min_heapify(Node* &a,int i,int length)

{

   int smallest = i;

   while(smallest <= length -1)

   {

       int left =2*smallest +1;

       int right =2*smallest +2;

       int temp = smallest;

       if(left <= length -1 && a[left] < a[smallest])

       {

           smallest = left;

       }

       if(right <= length -1 && a[right] < a[smallest])

       {

           smallest = right;

       }

       if(smallest != temp)

       {

           Node exchange = a[smallest];

           a[smallest] = a[temp];

           a[temp] = exchange;

       }

       else

           break;

   }

}

void build_min_heap(Node* &a,int length)

{

   int root = length/2 -1;

   for(int i = root; i >=0; i--)

       min_heapify(a, i, length);

}

Node::Node()

{

   next = NULL;

}

Node::Node(int d)

{

   data = d;

   next = NULL;

}

Node::operator Node() const

{

   return data;

}

bool Node::operator<(const Node& temp)

{

   if(data < temp.data)

       returntrue;

   returnfalse;

}

List::List()

{

   first = NULL;

}

 

void List::insert(int d)

{

   Node* node = new Node(d);

   if(first == NULL)

       first = node;

   else

   {

       Node* temp = first->next;

       Node* prev = first;

       while(temp != NULL)

       {

           prev = temp;

           temp = temp->next;

       }

       prev->next = node;

   }

}

原文链接:http://www.cnblogs.com/shuaiwhu/archive/2011/03/20/2065077.html

 

原创粉丝点击