[英]In C++, why there is a requirement that lists must be sorted before merging
[英]Merging 8 sorted lists in c++, which algorithm should I use
我有8個排序列表,我需要合並到1個排序列表中。 我不知道這樣做的最好方法。 我在考慮以下幾點:
void merge_lists_inplace(list<int>& l1, const list<int>& l2)
{
list<int>::iterator end_it = l1.end();
--end_it;
copy(l2.begin(), l2.end(), back_inserter(l1));
++end_it;
inplace_merge(l1.begin(), end_it, l1.end());
}
list<int> merge_8_lists(list<int>[8] lists)
{
merge_lists_inplace(lists[0], lists[1]);
merge_lists_inplace(lists[2], lists[3]);
merge_lists_inplace(lists[4], lists[5]);
merge_lists_inplace(lists[6], lists[7]);
merge_lists_inplace(lists[0], lists[2]);
merge_lists_inplace(lists[4], lists[6]);
merge_lists_inplace(lists[0], lists[4]);
return lists[0];
}
但是最后擔心排序會更好嗎?
list<int> merge_8_lists(list<int>[8] lists)
{
for (int i = 1; i < 8; ++i)
copy(lists[i].begin(), lists[i].end(), back_inserter(lists[0]));
lists[0].sort();
return lists[0];
}
旁注:我不關心列表是否被修改。
合並排序的合並階段的簡單擴展可以使用優先級隊列 (例如, 堆 )在O(n lg m)時間(其中n =項目總數和m =列表數)中執行此操作。 偽代碼:
Let P = a priority queue of the sorted lists, sorted by the smallest element in each list
Let O = an empty output list
While P is not empty:
Let L = remove the minimum element from P
Remove the first element from L and add it to O
If L is not empty, add L to P
在C ++中一個簡單的(未經測試的!)具體實現:
#include <list>
#include <set>
template<typename T>
struct cmp_list {
bool operator()(const std::list<T> *a, const std::list<T> *b) const {
return a->front() < b->front();
}
};
template<typename T>
void merge_sorted_lists(std::list<T> &output, std::list<std::list<T> > &input)
{
// Use a std::set as our priority queue. This has the same complexity analysis as
// a heap, but has a higher constant factor.
// Implementing a min-heap is left as an exercise for the reader,
// as is a non-mutating version
std::set<std::list<T> *, cmp_list<T> > pq;
for ( typename std::list<std::list<T> >::iterator it = input.begin();
it != input.end(); it++)
{
if (it->empty())
continue;
pq.insert(&*it);
}
while (!pq.empty()) {
std::list<T> *p = *pq.begin();
pq.erase(pq.begin());
output.push_back(p->front());
p->pop_front();
if (!p->empty())
pq.insert(p);
}
}
您可以嘗試一次一個地應用合並排序到每個列表:
http://en.wikipedia.org/wiki/Merge_sort
這具有合並排序的算法。 基本上你會使用列表1和2並合並排序。 然后你將獲取新的組合列表並使用列表3進行排序,這將一直持續到你有一個完全排序的列表。
編輯:
實際上,因為您的列表已經排序,所以只需要合並排序的最后部分。 我會迭代地將列表組合成更大和更大的部分,同時對每個更大的列表進行排序,直到你有完整的列表,這實際上是合並排序在完成其分而治之的方法后所做的。
如果性能不是問題,我會最后對列表進行排序。 代碼更具可讀性,更短,並且不太可能被將來重新訪問代碼的人搞砸。
這是一種標准(盡管是8路)合並排序。
基本上你“打開”八個排序列表然后開始處理它們,每次提取最低值,例如:
# Open all lists.
open newlist for write
for i = 1 to 8:
open list(i) for read
end for
# Process forever (break inside loop).
while true:
# Indicate that there's no lowest value.
smallidx = -1
# Find lowest value input list.
for i = 1 to 8:
# Ignore lists that are empty.
if not list(i).empty:
# Choose this input list if it's the first or smaller
# than the current smallest.
if smallidx = 1:
smallidx = i
smallval = list(i).peek()
else:
if list(i).peek() < smallval:
smallidx = i
smallval = list(i).peek()
end if
end if
end if
end for
# No values left means stop processing.
if smallidx = -1:
exit while
end if
# Transfer smallest value then continue.
smallval = list(smallidx).get()
newlist.put(smallval)
end while
您想要合並排序 。 您的列表已經拆分,但不是一直到最小的級別。 你可能想這樣做:
unsorted_list = concatenate(list[0], list[1], list[2], ... , list[7]);
sorted_list = merge_sort(unsorted_list);
這不應該是消耗時間/內存的操作,因為連接應該添加從列表中的最后一個節點到下一個列表的第一個元素的鏈接。
基本上你正在做多路合並的一部分,除了你的東西已經排序...
http://lcm.csa.iisc.ernet.in/dsa/node211.html
只需找到每個數組中的最低值(幾乎用作堆棧)並將其放入輸出中,直到所有堆棧都為空...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.