これは、マージソートのアルゴリズムを変更することで実現できます。スカイラインのアルゴリズムは次のようになります。
ConstructSkyLine
ConstructSkyLine(List B ) --------------- O(nlogn)
{
If(B.size() == 1)
{
List skyLineList = new List();
SKYLINE = new SKYLINE(B.XL, B.XR, B.H);
skyLineList.add(SKYLINE);
Return skyLineList;
}
B1, B2 <-- Split(B);
List S1 <-- ConstructSkyLine(B1);
List S2 <-- ConstructSkyLine(B2);
List S <-- MergeSkyline(S1, S2);
Return S;
}
MergeSkyline
MergeSkyline(List S1, List S2) --------------- O(n)
{
List< SKYLINEENTRY> skylineEntryList = new ArrayList<SKYLINEENTRY>();
while (S1.isEmpty() && S2.isEmpty())--------------- O(n)
{
S1Item <-- S1.get(0);
S2Item <-- S2.get(0);
If (S1Item.XL < S2Item.XL)
{
Merge(S1, S2, skylineEntryList); --------------- O(n)
}
Else
{
Merge(S2, S1, skylineEntryList); --------------- O(n)
}
}
If(!S1.isEmpty())
{
skylineEntryList.add(S1);
}
If(!S2.isEmpty())
{
skylineEntryList.add(S2);
}
Retrun skylineEntryList;
}
マージ
Merge(S1, S2, skylineEntryList) --------------- O(n)
{
SKYLINEENTRY <-- null;
S1Item <-- S1.get(0);
S2Item <-- S2.get(0);
SKYLINEENTRY.XL = S1Item.XL;
If(S1Item.XR > S2Item.XL) // means over lap
{
If(S1Item.H > S2Item.H) // S1 is higher.
{
SKYLINEENTRY.XR = S1Item.XR;
SKYLINEENTRY.H = S1Item.H;
S1.remove(S1Item); --------------- O(n)
skylineEntryList.add(SKYLINEENTRY);
if(S2Item.XR < S1Item.XR) // full overlap
{
S2.remove(S2Item); --------------- O(n)
}
Else // partial overlap
{
S2Item.XL <-- S1Item.XR;
}
}
Else //S2 is higher
{
SKYLINEENTRY.XR = S2Item.XL;
SKYLINEENTRY.H = S1Item.H;
if(S2Item.XR < S1Item.XR) // full overlap with S2
{
S1Item.XL = S2Item.XR;
}
Else // partial overlap
{
S1.remove(S1Item); --------------- O(n)
}
skylineEntryList.add(SKYLINEENTRY);
}
}
Else // no overlap
{
SKYLINEENTRY.XR = S1Item.XR;
SKYLINEENTRY.H = S1Item.H;
S1.remove(S1Item); --------------- O(n)
skylineEntryList.add(SKYLINEENTRY);
}
}