Skip to content

Commit 4a6bd11

Browse files
committed
Adding tests and completed topological sort
1 parent 05b9ef2 commit 4a6bd11

File tree

7 files changed

+518
-26
lines changed

7 files changed

+518
-26
lines changed

Topological Sort/Topological Sort.playground/Contents.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,5 @@ graph.addEdge(fromNode: node11, toNode: node9)
2323
graph.addEdge(fromNode: node11, toNode: node10)
2424
graph.addEdge(fromNode: node8, toNode: node9)
2525

26-
print(graph.description, terminator: "")
2726

28-
graph.depthFirstSearch("5")
27+
graph.topologicalSort()
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
21
public class Graph: CustomStringConvertible {
32

4-
private var adjacencyLists: [String : [String]]
5-
3+
public typealias Node = String
4+
5+
private var adjacencyLists: [Node : [Node]]
6+
67
public init() {
7-
adjacencyLists = [String : [String]]()
8+
adjacencyLists = [Node : [Node]]()
89
}
910

10-
public func addNode(value: String) -> String {
11+
public func addNode(value: Node) -> Node {
1112
adjacencyLists[value] = []
1213
return value
1314
}
1415

15-
public func addEdge(fromNode from: String, toNode to: String) -> Bool {
16+
public func addEdge(fromNode from: Node, toNode to: Node) -> Bool {
1617
adjacencyLists[from]?.append(to)
1718
return adjacencyLists[from] != nil ? true : false
1819
}
@@ -21,9 +22,9 @@ public class Graph: CustomStringConvertible {
2122
return adjacencyLists.description
2223
}
2324

24-
private func adjacencyList(forValue: String) -> [String]? {
25+
private func adjacencyList(forNode node: Node) -> [Node]? {
2526
for (key, adjacencyList) in adjacencyLists {
26-
if key == forValue {
27+
if key == node {
2728
return adjacencyList
2829
}
2930
}
@@ -32,25 +33,59 @@ public class Graph: CustomStringConvertible {
3233
}
3334

3435
extension Graph {
35-
36-
public func depthFirstSearch(source: String) -> [String] {
37-
var result = [String]()
38-
var stack = Stack<String>()
39-
40-
result.append(source)
41-
stack.push(source)
42-
43-
while !stack.isEmpty {
44-
if let element = stack.pop(), temp = adjacencyList(element) {
45-
for node in temp {
46-
stack.push(node)
47-
result.append(node)
36+
37+
typealias InDegree = Int
38+
private func calculateInDegreeOfNodes() -> [Node : InDegree] {
39+
40+
var inDegrees = [Node : InDegree]()
41+
42+
for (node, _) in adjacencyLists {
43+
inDegrees[node] = 0
44+
}
45+
46+
for (_, adjacencyList) in adjacencyLists {
47+
for nodeInList in adjacencyList {
48+
inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1
49+
}
50+
}
51+
return inDegrees
52+
}
53+
54+
private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] {
55+
var result = [source]
56+
visited[source] = true
57+
58+
if let adjacencyList = adjacencyList(forNode: source) {
59+
for nodeInAdjacencyList in adjacencyList {
60+
if !(visited[nodeInAdjacencyList] ?? false) {
61+
result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited))
4862
}
4963
}
5064
}
5165

5266
return result
5367
}
54-
}
55-
56-
68+
69+
public func topologicalSort() -> [Node] {
70+
71+
let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in
72+
return indegree == 0
73+
}).map({(node, indegree) in
74+
return node
75+
})
76+
77+
var visited = [Node : Bool]()
78+
79+
for (node, _) in adjacencyLists {
80+
visited[node] = false
81+
}
82+
83+
var result = [Node]()
84+
85+
for startNode in startNodes {
86+
result += depthFirstSearch(startNode, visited: &visited)
87+
}
88+
89+
return result
90+
}
91+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
// !$*UTF8*$!
2+
{
3+
archiveVersion = 1;
4+
classes = {
5+
};
6+
objectVersion = 46;
7+
objects = {
8+
9+
/* Begin PBXBuildFile section */
10+
61FB15B41C8D70B7000CEA54 /* TopologicalSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */; };
11+
61FB15BB1C8D70D7000CEA54 /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15B91C8D70D7000CEA54 /* Graph.swift */; };
12+
61FB15BC1C8D70D7000CEA54 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15BA1C8D70D7000CEA54 /* Stack.swift */; };
13+
/* End PBXBuildFile section */
14+
15+
/* Begin PBXFileReference section */
16+
61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TopologicalSort.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
17+
61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopologicalSort.swift; sourceTree = "<group>"; };
18+
61FB15B51C8D70B7000CEA54 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
19+
61FB15B91C8D70D7000CEA54 /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = "<group>"; };
20+
61FB15BA1C8D70D7000CEA54 /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = "<group>"; };
21+
/* End PBXFileReference section */
22+
23+
/* Begin PBXFrameworksBuildPhase section */
24+
61FB15AD1C8D70B7000CEA54 /* Frameworks */ = {
25+
isa = PBXFrameworksBuildPhase;
26+
buildActionMask = 2147483647;
27+
files = (
28+
);
29+
runOnlyForDeploymentPostprocessing = 0;
30+
};
31+
/* End PBXFrameworksBuildPhase section */
32+
33+
/* Begin PBXGroup section */
34+
61FB15A51C8D709E000CEA54 = {
35+
isa = PBXGroup;
36+
children = (
37+
61FB15B21C8D70B7000CEA54 /* TopologicalSort */,
38+
61FB15B11C8D70B7000CEA54 /* Products */,
39+
);
40+
sourceTree = "<group>";
41+
};
42+
61FB15B11C8D70B7000CEA54 /* Products */ = {
43+
isa = PBXGroup;
44+
children = (
45+
61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */,
46+
);
47+
name = Products;
48+
sourceTree = "<group>";
49+
};
50+
61FB15B21C8D70B7000CEA54 /* TopologicalSort */ = {
51+
isa = PBXGroup;
52+
children = (
53+
61FB15B91C8D70D7000CEA54 /* Graph.swift */,
54+
61FB15BA1C8D70D7000CEA54 /* Stack.swift */,
55+
61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */,
56+
61FB15B51C8D70B7000CEA54 /* Info.plist */,
57+
);
58+
path = TopologicalSort;
59+
sourceTree = "<group>";
60+
};
61+
/* End PBXGroup section */
62+
63+
/* Begin PBXNativeTarget section */
64+
61FB15AF1C8D70B7000CEA54 /* TopologicalSort */ = {
65+
isa = PBXNativeTarget;
66+
buildConfigurationList = 61FB15B61C8D70B7000CEA54 /* Build configuration list for PBXNativeTarget "TopologicalSort" */;
67+
buildPhases = (
68+
61FB15AC1C8D70B7000CEA54 /* Sources */,
69+
61FB15AD1C8D70B7000CEA54 /* Frameworks */,
70+
61FB15AE1C8D70B7000CEA54 /* Resources */,
71+
);
72+
buildRules = (
73+
);
74+
dependencies = (
75+
);
76+
name = TopologicalSort;
77+
productName = TopologicalSort;
78+
productReference = 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */;
79+
productType = "com.apple.product-type.bundle.unit-test";
80+
};
81+
/* End PBXNativeTarget section */
82+
83+
/* Begin PBXProject section */
84+
61FB15A61C8D709E000CEA54 /* Project object */ = {
85+
isa = PBXProject;
86+
attributes = {
87+
LastSwiftUpdateCheck = 0720;
88+
LastUpgradeCheck = 0720;
89+
TargetAttributes = {
90+
61FB15AF1C8D70B7000CEA54 = {
91+
CreatedOnToolsVersion = 7.2.1;
92+
};
93+
};
94+
};
95+
buildConfigurationList = 61FB15A91C8D709E000CEA54 /* Build configuration list for PBXProject "TopologicalSort" */;
96+
compatibilityVersion = "Xcode 3.2";
97+
developmentRegion = English;
98+
hasScannedForEncodings = 0;
99+
knownRegions = (
100+
en,
101+
);
102+
mainGroup = 61FB15A51C8D709E000CEA54;
103+
productRefGroup = 61FB15B11C8D70B7000CEA54 /* Products */;
104+
projectDirPath = "";
105+
projectRoot = "";
106+
targets = (
107+
61FB15AF1C8D70B7000CEA54 /* TopologicalSort */,
108+
);
109+
};
110+
/* End PBXProject section */
111+
112+
/* Begin PBXResourcesBuildPhase section */
113+
61FB15AE1C8D70B7000CEA54 /* Resources */ = {
114+
isa = PBXResourcesBuildPhase;
115+
buildActionMask = 2147483647;
116+
files = (
117+
);
118+
runOnlyForDeploymentPostprocessing = 0;
119+
};
120+
/* End PBXResourcesBuildPhase section */
121+
122+
/* Begin PBXSourcesBuildPhase section */
123+
61FB15AC1C8D70B7000CEA54 /* Sources */ = {
124+
isa = PBXSourcesBuildPhase;
125+
buildActionMask = 2147483647;
126+
files = (
127+
61FB15BB1C8D70D7000CEA54 /* Graph.swift in Sources */,
128+
61FB15BC1C8D70D7000CEA54 /* Stack.swift in Sources */,
129+
61FB15B41C8D70B7000CEA54 /* TopologicalSort.swift in Sources */,
130+
);
131+
runOnlyForDeploymentPostprocessing = 0;
132+
};
133+
/* End PBXSourcesBuildPhase section */
134+
135+
/* Begin XCBuildConfiguration section */
136+
61FB15AA1C8D709E000CEA54 /* Debug */ = {
137+
isa = XCBuildConfiguration;
138+
buildSettings = {
139+
};
140+
name = Debug;
141+
};
142+
61FB15AB1C8D709E000CEA54 /* Release */ = {
143+
isa = XCBuildConfiguration;
144+
buildSettings = {
145+
};
146+
name = Release;
147+
};
148+
61FB15B71C8D70B7000CEA54 /* Debug */ = {
149+
isa = XCBuildConfiguration;
150+
buildSettings = {
151+
ALWAYS_SEARCH_USER_PATHS = NO;
152+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
153+
CLANG_CXX_LIBRARY = "libc++";
154+
CLANG_ENABLE_MODULES = YES;
155+
CLANG_ENABLE_OBJC_ARC = YES;
156+
CLANG_WARN_BOOL_CONVERSION = YES;
157+
CLANG_WARN_CONSTANT_CONVERSION = YES;
158+
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
159+
CLANG_WARN_EMPTY_BODY = YES;
160+
CLANG_WARN_ENUM_CONVERSION = YES;
161+
CLANG_WARN_INT_CONVERSION = YES;
162+
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
163+
CLANG_WARN_UNREACHABLE_CODE = YES;
164+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
165+
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
166+
COPY_PHASE_STRIP = NO;
167+
DEBUG_INFORMATION_FORMAT = dwarf;
168+
ENABLE_STRICT_OBJC_MSGSEND = YES;
169+
ENABLE_TESTABILITY = YES;
170+
GCC_C_LANGUAGE_STANDARD = gnu99;
171+
GCC_DYNAMIC_NO_PIC = NO;
172+
GCC_NO_COMMON_BLOCKS = YES;
173+
GCC_OPTIMIZATION_LEVEL = 0;
174+
GCC_PREPROCESSOR_DEFINITIONS = (
175+
"DEBUG=1",
176+
"$(inherited)",
177+
);
178+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
179+
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
180+
GCC_WARN_UNDECLARED_SELECTOR = YES;
181+
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
182+
GCC_WARN_UNUSED_FUNCTION = YES;
183+
GCC_WARN_UNUSED_VARIABLE = YES;
184+
INFOPLIST_FILE = TopologicalSort/Info.plist;
185+
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
186+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
187+
MTL_ENABLE_DEBUG_INFO = YES;
188+
ONLY_ACTIVE_ARCH = YES;
189+
PRODUCT_BUNDLE_IDENTIFIER = com.alihafizji.TopologicalSort;
190+
PRODUCT_NAME = "$(TARGET_NAME)";
191+
SDKROOT = iphoneos;
192+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
193+
};
194+
name = Debug;
195+
};
196+
61FB15B81C8D70B7000CEA54 /* Release */ = {
197+
isa = XCBuildConfiguration;
198+
buildSettings = {
199+
ALWAYS_SEARCH_USER_PATHS = NO;
200+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
201+
CLANG_CXX_LIBRARY = "libc++";
202+
CLANG_ENABLE_MODULES = YES;
203+
CLANG_ENABLE_OBJC_ARC = YES;
204+
CLANG_WARN_BOOL_CONVERSION = YES;
205+
CLANG_WARN_CONSTANT_CONVERSION = YES;
206+
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
207+
CLANG_WARN_EMPTY_BODY = YES;
208+
CLANG_WARN_ENUM_CONVERSION = YES;
209+
CLANG_WARN_INT_CONVERSION = YES;
210+
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
211+
CLANG_WARN_UNREACHABLE_CODE = YES;
212+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
213+
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
214+
COPY_PHASE_STRIP = NO;
215+
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
216+
ENABLE_NS_ASSERTIONS = NO;
217+
ENABLE_STRICT_OBJC_MSGSEND = YES;
218+
GCC_C_LANGUAGE_STANDARD = gnu99;
219+
GCC_NO_COMMON_BLOCKS = YES;
220+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
221+
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
222+
GCC_WARN_UNDECLARED_SELECTOR = YES;
223+
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
224+
GCC_WARN_UNUSED_FUNCTION = YES;
225+
GCC_WARN_UNUSED_VARIABLE = YES;
226+
INFOPLIST_FILE = TopologicalSort/Info.plist;
227+
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
228+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
229+
MTL_ENABLE_DEBUG_INFO = NO;
230+
PRODUCT_BUNDLE_IDENTIFIER = com.alihafizji.TopologicalSort;
231+
PRODUCT_NAME = "$(TARGET_NAME)";
232+
SDKROOT = iphoneos;
233+
VALIDATE_PRODUCT = YES;
234+
};
235+
name = Release;
236+
};
237+
/* End XCBuildConfiguration section */
238+
239+
/* Begin XCConfigurationList section */
240+
61FB15A91C8D709E000CEA54 /* Build configuration list for PBXProject "TopologicalSort" */ = {
241+
isa = XCConfigurationList;
242+
buildConfigurations = (
243+
61FB15AA1C8D709E000CEA54 /* Debug */,
244+
61FB15AB1C8D709E000CEA54 /* Release */,
245+
);
246+
defaultConfigurationIsVisible = 0;
247+
defaultConfigurationName = Release;
248+
};
249+
61FB15B61C8D70B7000CEA54 /* Build configuration list for PBXNativeTarget "TopologicalSort" */ = {
250+
isa = XCConfigurationList;
251+
buildConfigurations = (
252+
61FB15B71C8D70B7000CEA54 /* Debug */,
253+
61FB15B81C8D70B7000CEA54 /* Release */,
254+
);
255+
defaultConfigurationIsVisible = 0;
256+
};
257+
/* End XCConfigurationList section */
258+
};
259+
rootObject = 61FB15A61C8D709E000CEA54 /* Project object */;
260+
}

0 commit comments

Comments
 (0)