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

CLRS 6.5-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都弄在一起,首先是两个类List和Node,然后就是两个关于最小堆操作的函数,代码有点长,但是一点都不难,因为你肯定看过最大堆的操作,那么最小堆就大同小异了:

#include <iostream>
using namespace std;

class Node
{
public:
  Node
* next;
  int data;

  Node();
  Node(
int d);

  operator Node() const;
  //只需用到"<"号
  bool operator < (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;
  }
  return 0;
}

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)
    return true;
  return false;
}

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;
  }
}
---
可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明
原文地址:https://www.cnblogs.com/null00/p/2065077.html