Skip to content

Commit 6a80b21

Browse files
frankymacster64json
authored andcommitted
Add Cycle Detection (algorithm-visualizer#22)
1 parent 8bd066f commit 6a80b21

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Cycle Detection
2+
"Floyd's cycle-finding algorithm is a pointer algorithm that uses only two pointers, which move through the sequence at different speeds"
3+
4+
## References
5+
* [Wikipedia](https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_Tortoise_and_Hare)
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// import visualization libraries {
2+
const { Array2DTracer, Layout, LogTracer, GraphTracer, Tracer, VerticalLayout } = require('algorithm-visualizer');
3+
// }
4+
5+
6+
// define tracer variables {
7+
function ListNode(val) {
8+
this.val = val
9+
this.next = null
10+
}
11+
12+
const node0 = new ListNode(0)
13+
const node1 = new ListNode(1)
14+
const node2 = new ListNode(2)
15+
const node3 = new ListNode(3)
16+
const node4 = new ListNode(4)
17+
const node5 = new ListNode(5)
18+
const node6 = new ListNode(6)
19+
20+
const list = node0
21+
list.next = node1
22+
list.next.next = node2
23+
list.next.next.next = node3
24+
list.next.next.next.next = node4
25+
list.next.next.next.next.next = node5
26+
list.next.next.next.next.next.next = node6
27+
list.next.next.next.next.next.next.next = node2
28+
29+
const graphTracer = new GraphTracer("Linked List").directed()
30+
const logTracer = new LogTracer("Console")
31+
Layout.setRoot(new VerticalLayout([graphTracer, logTracer]))
32+
33+
graphTracer.addNode(node0.val)
34+
graphTracer.addNode(node1.val)
35+
graphTracer.addNode(node2.val)
36+
graphTracer.addNode(node3.val)
37+
graphTracer.addNode(node4.val)
38+
graphTracer.addNode(node5.val)
39+
graphTracer.addNode(node6.val)
40+
graphTracer.addEdge(node0.val, node1.val)
41+
graphTracer.addEdge(node1.val, node2.val)
42+
graphTracer.addEdge(node2.val, node3.val)
43+
graphTracer.addEdge(node3.val, node4.val)
44+
graphTracer.addEdge(node4.val, node5.val)
45+
graphTracer.addEdge(node5.val, node6.val)
46+
graphTracer.addEdge(node6.val, node2.val)
47+
Tracer.delay()
48+
// }
49+
50+
var listHasCycle = function(head) {
51+
// visualize {
52+
graphTracer.select(head.val)
53+
graphTracer.visit(head.val)
54+
Tracer.delay()
55+
graphTracer.deselect(head.val)
56+
graphTracer.leave(head.val)
57+
// }
58+
59+
// 1. is there a cycle?
60+
let slow = head.next
61+
let fast = head.next.next
62+
// visualize {
63+
graphTracer.select(slow.val)
64+
graphTracer.visit(fast.val)
65+
Tracer.delay()
66+
graphTracer.deselect(slow.val)
67+
graphTracer.leave(fast.val)
68+
// }
69+
while (slow !== fast) {
70+
slow = slow.next
71+
fast = fast.next.next
72+
// visualize {
73+
graphTracer.select(slow.val)
74+
graphTracer.visit(fast.val)
75+
Tracer.delay()
76+
graphTracer.deselect(slow.val)
77+
graphTracer.leave(fast.val)
78+
// }
79+
}
80+
81+
// 2. where does the cycle start?
82+
let cycleStartPosition = 0
83+
slow = head
84+
// visualize {
85+
graphTracer.select(slow.val)
86+
graphTracer.visit(fast.val)
87+
Tracer.delay()
88+
graphTracer.deselect(slow.val)
89+
graphTracer.leave(fast.val)
90+
// }
91+
while (slow !== fast) {
92+
slow = slow.next
93+
fast = fast.next
94+
cycleStartPosition += 1
95+
// visualize {
96+
graphTracer.select(slow.val)
97+
graphTracer.visit(fast.val)
98+
Tracer.delay()
99+
graphTracer.deselect(slow.val)
100+
graphTracer.leave(fast.val)
101+
// }
102+
}
103+
104+
// 3. what is the length of the cycle?
105+
let cycleLength = 1
106+
fast = slow.next
107+
// visualize {
108+
graphTracer.select(slow.val)
109+
graphTracer.visit(fast.val)
110+
Tracer.delay()
111+
graphTracer.deselect(slow.val)
112+
graphTracer.leave(fast.val)
113+
// }
114+
while (slow !== fast) {
115+
fast = fast.next
116+
cycleLength += 1
117+
// visualize {
118+
graphTracer.select(slow.val)
119+
graphTracer.visit(fast.val)
120+
Tracer.delay()
121+
graphTracer.deselect(slow.val)
122+
graphTracer.leave(fast.val)
123+
// }
124+
}
125+
126+
return {
127+
cycleLength,
128+
cycleStartPosition,
129+
}
130+
}
131+
// log {
132+
const res = listHasCycle(list)
133+
logTracer.print(`cycle start position: ${res.cycleStartPosition}`)
134+
logTracer.print("\n")
135+
logTracer.print(`cycle length: ${res.cycleLength}`)
136+
// }

0 commit comments

Comments
 (0)