提交 2c63baa5 编写于 作者: A Alexey Milovidov

Merge remote-tracking branch 'origin/better-priority-queue' into gcc-libcxx

#pragma once
#include <cassert>
#include <vector>
#include <algorithm>
......@@ -210,6 +211,8 @@ struct SortCursorWithCollation
};
/** Allows to fetch data from multiple sort cursors in sorted order (merging sorted data streams).
*/
template <typename Cursor>
class SortingHeap
{
......@@ -232,13 +235,15 @@ public:
void next()
{
if (current()->isValid())
assert(isValid());
if (!current()->isLast())
{
current()->next();
updateTopHeap(queue.begin(), queue.end());
updateTop();
}
else
queue.erase(queue.begin());
removeTop();
}
private:
......@@ -246,15 +251,17 @@ private:
Container queue;
/// This is adapted version of the function __sift_down from libc++.
template <typename It>
static void updateTopHeap(It begin, It end)
/// Why cannot simply use std::priority_queue?
/// - because it doesn't support updating the top element and requires pop and push instead.
void updateTop()
{
size_t size = end - begin;
size_t size = queue.size();
if (size < 2)
return;
size_t child_idx = 1;
It child_it = begin + 1;
auto begin = queue.begin();
auto child_it = begin + 1;
/// Right child exists and is greater than left child.
if (size > 2 && *child_it < *(child_it + 1))
......@@ -293,6 +300,11 @@ private:
} while (!(*child_it < top));
*curr_it = std::move(top);
}
void removeTop()
{
std::pop_heap(queue.begin(), queue.end());
}
};
}
......@@ -178,9 +178,9 @@ Block MergeSortingBlocksBlockInputStream::readImpl()
template <typename TSortingHeap>
Block MergeSortingBlocksBlockInputStream::mergeImpl(TSortingHeap & queue)
{
size_t num_columns = blocks[0].columns();
size_t num_columns = header.columns();
MutableColumns merged_columns = blocks[0].cloneEmptyColumns();
MutableColumns merged_columns = header.cloneEmptyColumns();
/// TODO: reserve (in each column)
/// Take rows from queue in right order and push to 'merged'.
......@@ -189,31 +189,31 @@ Block MergeSortingBlocksBlockInputStream::mergeImpl(TSortingHeap & queue)
{
auto current = queue.current();
/// Append a row from queue.
for (size_t i = 0; i < num_columns; ++i)
merged_columns[i]->insertFrom(*current->all_columns[i], current->pos);
if (queue.isValid())
queue.next();
else
break;
++total_merged_rows;
++merged_rows;
/// We don't need more rows because of limit has reached.
if (limit && total_merged_rows == limit)
{
auto res = blocks[0].cloneWithColumns(std::move(merged_columns));
blocks.clear();
return res;
break;
}
++merged_rows;
queue.next();
/// It's enough for current output block but we will continue.
if (merged_rows == max_merged_block_size)
return blocks[0].cloneWithColumns(std::move(merged_columns));
break;
}
if (merged_rows == 0)
return {};
return blocks[0].cloneWithColumns(std::move(merged_columns));
return header.cloneWithColumns(std::move(merged_columns));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册