[Algorithm] ๋ฐ์ดํฐ ์ถ๊ฐ, ์ญ์ , ์ ๋ ฌ๋ก ๋ณด๋ BFS / DFS ํ์ ์๊ณ ๋ฆฌ์ฆ
์์ ๋ฐ์ดํฐ
๋จ์ด ํน์ ๋ฌธ์ฅ๋ถํธ('
์ํฌ์คํธ๋กํผ ์ ์ธ)๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ถ๋ฆฌํ ํ ํฐ ์ธ๋ฑ์ค ์ ๋ณด๊ฐ ๋ด๊ธฐ๋ Part ๊ฐ์ฒด๊ฐ ์๋ค. ์ด Part ๊ฐ์ฒด๋ child
๋ฐฐ์ด์ ๊ฐ์ง๋ฉฐ, child
๋ฐฐ์ด์ ๊ฐ ์์์ธ Part๋ ๋ถ๋ชจ Part์ ํ ํฐ ์ธ๋ฑ์ค ๋ฒ์ ๋ด์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง๋ค. ์๋ฅผ๋ค์ด ๋ถ๋ชจ Part์ ํ ํฐ ์ธ๋ฑ์ค ๋ฒ์๊ฐ 2~13์ด๋ผ๋ฉด ์์ Part์ ํ ํฐ ์ธ๋ฑ์ค๋ 3~13(3~13, 4~13, ...) ํน์ 2~12(2~12, 2~11, ...) ๋ฒ์๋ฅผ ๊ฐ์ง๋ค.
[
// parts ๋ฐฐ์ด
{
id: 0, // part
begin: 2,
end: 13,
kc: [{ id: 'kc-1', /* ... */ }],
child: [ // parts ๋ฐฐ์ด
{
id: 1, // part
begin: 4,
end: 13,
kc: [{ id: 'kc-2', /* ... */ }],
child: [{ /* ... */ }],
},
],
},
{
// ...
},
];
์์ ๊ฐ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์์ ๊ฐ Part์ kc
๋ฐฐ์ด์ ์๋ ํน์ ์์๋ฅผ ์ถ๊ฐ/์ญ์ ํ๋๊ฒ ๋ชฉ์ . ์ฐธ๊ณ ๋ก kc
๋ฐฐ์ด์ begin~end ๋ฒ์์ ๋ฌธ๋ฒ์ ํน์ฑ์ ๋ํ๋ธ๋ค.
KC ์ญ์ | BFS
๋ชฉํ
ํ์ฌ ๋ ๋ฒจ์ ์๋ ๋ชจ๋ part์ kc
๋ฐฐ์ด์ ํ์ํ๋ฉด์ ์
๋ ฅ๋ฐ์ kcId
๋ฅผ ์ฐพ์ ์ญ์ ํ๋ค. ํ์ฌ ๋ ๋ฒจ ๊น์ด์์ kcId
๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด ๋ค์ ๋ ๋ฒจ ๊น์ด์ part ์์๋ค์ ๊ฒ์ฌํ๋ ๋๋น ์ฐ์ ํ์ ๋ฐฉ์ ์ฌ์ฉ.
๊ตฌํ
์ฌ๊ทํจ์ ๋์ queue๋ก ๊ตฌํ. while ๋ฌธ์ ์ํํ ๋๋ง๋ค queue ๊ฐ์ฅ ์์ชฝ ์์๋ฅผ ์ถ์ถํ ํ ๊ฒ์ฌ. part.kc
๋ฐฐ์ด ๋ด์์ ์
๋ ฅ๋ฐ์ kcId
๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด ํ์ฌ part์ ๋ชจ๋ child ์์๋ฅผ queue์ ์ถ๊ฐํ๊ณ ํ์ ๋ฐ๋ณต.
const removeKCById = (parts: Array<Part>, kcId: KC['id']) => {
const newParts: Array<Part> = structuredClone(parts); // ๊น์ ๋ณต์ฌ
const queue = [...newParts]; // ํ์ํ parts
let found = false;
while (queue.length > 0) {
const currentPart = queue.shift();
if (currentPart?.kc.length) {
// filter ํ์ part.kc ๋ฐฐ์ด ๊ธธ์ด์ ๋น๊ตํ๊ธฐ ์ํด ์๋ณธ kc ๋ฐฐ์ด ๊ธธ์ด ์์ ์ ์ฅ
const originalLength = currentPart.kc.length;
// ์
๋ ฅ๋ฐ์ kc.id๋ฅผ ์ฐพ์ผ๋ฉด kc ๋ฐฐ์ด์์ ์ ์ธ
currentPart.kc = currentPart.kc.filter(({ id }) => id !== kcId);
// originalLength ๊ธธ์ด๊ฐ ๋ ํฌ๋ฉด kc.id๋ฅผ ์ฐพ์ ์ญ์ ํ์ผ๋ฏ๋ก ํจ์ ์ข
๋ฃ
if (originalLength > currentPart.kc.length) {
found = true;
break;
}
}
// ํ์ฌ part.kc ๋ฐฐ์ด์์ ์
๋ ฅ๋ฐ์ kc.id๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด queue์ ์ถ๊ฐํ ํ ์ ๊ณผ์ ๋ฐ๋ณต
if (currentPart?.child?.length) queue.push(...currentPart.child);
}
if (!found) console.warn(`No KC with id ${kcId} was found.`);
return newParts;
};
KC ์ถ๊ฐ | DFS
๋ชฉํ
๋ฌธ์์ด์ ํ ํฐ ์ธ๋ฑ์ค๋ฅผ ๋ํ๋ด๋ begin/end์ ๋ฌธ๋ฒ์ ํน์ฑ์ ๋ํ๋ด๋ kc
๋ฅผ ๋ฐ์, ํด๋น ์ธ๋ฑ์ค ๋ฒ์์ ์ผ์นํ๋ part๋ฅผ ์ฐพ์ kc
๋ฐฐ์ด์ ์ถ๊ฐํ๋ค. ์ผ์นํ๋ part๋ฅผ ์ฐพ์ง ๋ชปํ๋ค๋ฉด ์๋ก์ด part๋ฅผ ์์ฑํ๋ค.
begin/end ๋ฒ์๋ฅผ ํฌํจํ์ง ์๋ part์ ์์์ ํ์ํ ํ์๊ฐ ์๋ค.
์๋ฅผ๋ค์ด begin 8, end 9๋ฅผ ์ธ์๋ก ๋ฐ์์ ๋ ํด๋น ์ธ๋ฑ์ค ๋ฒ์๋ฅผ ํฌํจํ๋, begin ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ๊ณ end ๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ part๋ฅผ ๊น์ด ์ฐ์ ๋ฐฉ์์ผ๋ก ํ์ํด ๋๊ฐ์ผ ํ๋ค(์ ์ด๋ฏธ์ง ์ผ์ชฝ ์ผ์ด์ค ์ฐธ๊ณ ).
๊ตฌํ
const addKCToPart = (parts: Part[], begin: number, end: number, kc: KC) => {
const newParts: Array<Part> = structuredClone(parts); // ๊น์ ๋ณต์ฌ
for (const part of newParts) {
// begin, end ๋ฒ์์ ์ ํํ ์ผ์นํ๋ค๋ฉด part.kc ๋ฐฐ์ด์ ์ถ๊ฐํ ํ ํจ์ ์ข
๋ฃ
if (part.begin === begin && part.end === end) {
part.kc.push(kc);
return newParts;
}
// begin ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ๊ณ , end๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ผ๋ฉด ๋ฒ์๋ด์ ์์ผ๋ฏ๋ก ์์ part ํ์
if (part.begin <= begin && part.end >= end) {
// ์์ part ์ฌ๊ท์ ์ผ๋ก ํ์
part.child = addKCToPart(part.child, begin, end, kc);
return newParts;
}
}
/** ๋งค์นญํ๋ part ์์ผ๋ฉด ์๋ก์ด part ์์ฑ */
newParts.push({
id: uuidv4(),
begin,
end,
kc: [kc],
child: [],
});
return newParts;
};
์๋ก์ด ๋ ธ๋(Part)๋ฅผ ์ถ๊ฐํ๊ณ ํด๋น ๋ฒ์๋ด ๋ค๋ฅธ ๋ ธ๋๋ฅผ ์์์ผ๋ก ์ฎ๊ธฐ๋ ์ฌํ ๋ฒ์ โผ
const cloneParts = (parts: Part[]): Part[] => structuredClone(parts);
const moveToPart = (parts: Part[], begin: number, end: number): Part[] => {
// flatMap์ 1depth๊น์ง ๋ฐฐ์ด์ ํผ์น๊ณ , ๋น ๋ฐฐ์ด์ ๋ฐํํ๋ฉด ๊ฒฐ๊ณผ์ ํฌํจํ์ง ์์
return parts.flatMap((part) => {
if (
(part.begin > begin && part.end <= end) ||
(part.begin >= begin && part.end < end)
)
return [part];
else return moveToPart(part.child, begin, end);
});
};
export const addKCToPart = (
parts: Part[],
begin: number,
end: number,
kc: KC,
): Part[] => {
const newParts = cloneParts(parts);
for (const part of newParts) {
if (part.begin === begin && part.end === end) {
part.kc.push(kc);
return newParts;
}
if (part.begin <= begin && part.end >= end) {
part.child = addKCToPart(part.child, begin, end, kc, onInvalidCallback);
return newParts;
}
}
if (newParts.length === 0) return [getNewPart(begin, end, [kc])];
const left = getNewPart(begin, end, [kc]);
const right = getNewPart(end, newParts[newParts.length - 1].end);
left.child = moveToPart(newParts, left.begin, left.end);
right.child = moveToPart(newParts, right.begin, right.end);
return [left, right];
};
Empty Part ์ญ์ | DFS
part.kc
์ part.child
๊ธธ์ด๊ฐ ๋ชจ๋ 0์ด๋ฉด ๋์ด์ ์ฌ์ฉํ์ง ์๋ part์ด๋ฏ๋ก ์ญ์ ํด์ผ ํ๋ค. ๋ชจ๋ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํด์ ํ์ธํด์ผ ํ๋ฏ๋ก DFS, BFS ์ด๋ค ๊ฒ์ ์ฌ์ฉํด๋ ๋ฌด๋ฐฉํ๋ค. part.child
๊ธธ์ด๊ฐ 1์ด์์ด๋ฉด ์ฌ์ฉํ๋ part๋ก ํ๋จํ๋ฏ๋ก, ๊ฐ์ฅ ๊น์ ๋
ธ๋๊ฐ ๋น์ด์์ ๊ฐ๋ฅ์ฑ์ด ๋ง๋ค. ๋ฐ๋ผ์ ๊น์ด ์ฐ์ ํ์์ผ๋ก ๊ตฌํํ๋ค.
const removeEmptyKCParts = (parts: Part[]) => {
return parts.reduce((acc: Part[], part: Part) => {
// ๊น์ด ์ฐ์ ํ์์ ์ํด child๊ฐ ์๋ค๋ฉด child ์ฌ๊ทํธ์ถ
if (part.child.length) part.child = removeEmptyKCParts(part.child);
// ํ์ฌ part์ ์ฌ์ฉ ์ฌ๋ถ์ ๋ํ ์กฐ๊ฑด
if (part.kc.length || part.child.length) {
acc.push(part);
}
return acc;
}, []);
};
Parts ์ ๋ ฌ | DFS
parts
๋ฐฐ์ด์์ ๊ฐ์ฅ ๋์ ๋ฒ์์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง๋ part๊ฐ ๋ฐฐ์ด ์์ชฝ์ ์ค๋๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ๋ค. begin + end ํฉ์ด ํด ์๋ก ๋ ๋์ ๋ฒ์๋ฅผ ๊ฐ์ง๋ค๊ณ ๋ณผ ์ ์๋ค. ์ ๋ ฌ ํ์ ๊ฐ part๋ฅผ ์ํํ๋ฉด์ child
๋ฐฐ์ด(parts) ๊ธธ์ด๊ฐ 1 ์ด์์ธ์ง ๊ฒ์ฌํ๊ณ , ์ฐธ์ด๋ฉด ์ฌ๊ทํธ์ถํด์ ์์ parts
๋ฐฐ์ด๋ ์ ๋ ฌํ๋ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
const sortParts = (parts: Part[]) => {
return parts
.sort((a, b) => b.begin + b.end - (a.begin + a.end))
.map((part) => {
if (part.child.length) part.child = sortParts(part.child);
return part;
});
};
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JS] ์์ด ์ถ์ฝ์ด ๊ด๋ จ ์ ํธ๋ฆฌํฐ ํจ์ ๋ชจ์ (0) | 2024.05.22 |
---|---|
[Algorithm] ๋ณต์กํ DOM ์์ ๋ก ๋ณด๋ DFS ํ์ ์๊ณ ๋ฆฌ์ฆ (0) | 2024.05.22 |
[React/JS] ๋๋๊ทธํ ๋ฌธ์์ด ๋ถ๋ฆฌ(๋ฉํ)ํ๊ธฐ / Selection API (0) | 2024.05.21 |
[React] ๋ฆฌ์กํธ ๋์์ฑ ๋ ๋๋ง(Concurrent) ํบ์๋ณด๊ธฐ (1) | 2024.05.20 |
[Express] req.query vs req.params (0) | 2024.05.19 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[JS] ์์ด ์ถ์ฝ์ด ๊ด๋ จ ์ ํธ๋ฆฌํฐ ํจ์ ๋ชจ์
[JS] ์์ด ์ถ์ฝ์ด ๊ด๋ จ ์ ํธ๋ฆฌํฐ ํจ์ ๋ชจ์
2024.05.22 -
[Algorithm] ๋ณต์กํ DOM ์์ ๋ก ๋ณด๋ DFS ํ์ ์๊ณ ๋ฆฌ์ฆ
[Algorithm] ๋ณต์กํ DOM ์์ ๋ก ๋ณด๋ DFS ํ์ ์๊ณ ๋ฆฌ์ฆ
2024.05.22 -
[React/JS] ๋๋๊ทธํ ๋ฌธ์์ด ๋ถ๋ฆฌ(๋ฉํ)ํ๊ธฐ / Selection API
[React/JS] ๋๋๊ทธํ ๋ฌธ์์ด ๋ถ๋ฆฌ(๋ฉํ)ํ๊ธฐ / Selection API
2024.05.21 -
[React] ๋ฆฌ์กํธ ๋์์ฑ ๋ ๋๋ง(Concurrent) ํบ์๋ณด๊ธฐ
[React] ๋ฆฌ์กํธ ๋์์ฑ ๋ ๋๋ง(Concurrent) ํบ์๋ณด๊ธฐ
2024.05.20