Skip to content

Commit 8e8d8e6

Browse files
committed
01. Singly Linked List
1 parent 2f96362 commit 8e8d8e6

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
(ns clj-dsa.data-structures.linked-list.singly-linked-list
2+
"Singly Linked List")
3+
4+
(definterface INode
5+
(set_data [d])
6+
(get_data [])
7+
(set_addr [a])
8+
(get_addr []))
9+
10+
(deftype Node [^:volatile-mutable data ^:volatile-mutable addr]
11+
INode
12+
(set_data
13+
[_ d]
14+
(set! data d))
15+
(get_data
16+
[_]
17+
data)
18+
(set_addr
19+
[_ a]
20+
(set! addr a))
21+
(get_addr
22+
[_]
23+
addr))
24+
25+
(definterface ISLL
26+
(set_head [h])
27+
(get_head [])
28+
(set_tail [t])
29+
(get_tail [])
30+
(print_sll [])
31+
(push_front [d])
32+
(push_back [d])
33+
(pop_front [])
34+
(pop_back [])
35+
(insert [i v])
36+
(search [v]))
37+
38+
(deftype SLL [^:volatile-mutable head ^:volatile-mutable tail]
39+
ISLL
40+
(set_head
41+
[_ h]
42+
(set! head h))
43+
(get_head
44+
[_]
45+
head)
46+
(set_tail
47+
[_ t]
48+
(set! tail t))
49+
(get_tail
50+
[_]
51+
tail)
52+
(print_sll
53+
[_]
54+
(when head
55+
(loop [current-head head]
56+
(let [current-head-data (.get_data current-head)
57+
current-head-address (.get_addr current-head)]
58+
(print (str current-head-data (when current-head-address "->")))
59+
(when current-head-address
60+
(recur current-head-address))))))
61+
(push_front
62+
[this d]
63+
(let [new-node (->Node d nil)]
64+
(if-not head
65+
(do
66+
(.set_head this new-node)
67+
(.set_tail this new-node))
68+
(do
69+
(.set_addr new-node head)
70+
(.set_head this new-node)))))
71+
(push_back
72+
[this d]
73+
(let [new-node (->Node d nil)]
74+
(if-not head
75+
(do
76+
(.set_head this new-node)
77+
(.set_tail this new-node))
78+
(do
79+
(.set_addr tail new-node)
80+
(.set_tail this new-node)))))
81+
(pop_front
82+
[this]
83+
(when head
84+
(let [next-node (.get_addr head)]
85+
(.set_head this next-node))))
86+
(pop_back
87+
[this]
88+
(when head
89+
(loop [current-head head]
90+
(if-let [current-head-address (.get_addr current-head)]
91+
(if (= current-head-address tail)
92+
(do
93+
(.set_addr current-head nil)
94+
(.set_tail this current-head))
95+
(recur current-head-address))
96+
;; List only has one element; remove it
97+
(do
98+
(.set_head this nil)
99+
(.set_tail this nil))))))
100+
(insert
101+
[this i v]
102+
(when head
103+
(if (= 0 i)
104+
(.push_front this v)
105+
(loop [current-head head
106+
index 0]
107+
(if (= index (dec i))
108+
;; i.e. Found the node before the new (to be inserted) node
109+
(let [new-node (->Node v (.get_addr current-head))]
110+
(.set_addr current-head new-node))
111+
(recur
112+
(.get_addr current-head)
113+
(inc index)))))))
114+
(search
115+
[_ v]
116+
(when head
117+
(loop [current-head head
118+
index 0]
119+
(if current-head
120+
(if (= (.get_data current-head) v)
121+
index
122+
(recur
123+
(.get_addr current-head)
124+
(inc index)))
125+
-1)))))
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
(ns clj-dsa.data-structures.linked-list.singly-linked-list-test
2+
(:require
3+
[clojure.test :refer [deftest is]]
4+
[clj-dsa.data-structures.linked-list.singly-linked-list :as sll]))
5+
6+
(deftest test-node-creation
7+
(let [node (sll/->Node "data" nil)]
8+
(is (= "data" (.get_data node)))
9+
(is (= nil (.get_addr node)))))
10+
11+
(deftest test-set-and-get-head
12+
(let [sll (sll/->SLL nil nil)
13+
head-node (sll/->Node "head" nil)]
14+
(.set_head sll head-node)
15+
(is (= head-node (.get_head sll)))))
16+
17+
(deftest test-set-and-get-tail
18+
(let [sll (sll/->SLL nil nil)
19+
tail-node (sll/->Node "tail" nil)]
20+
(.set_tail sll tail-node)
21+
(is (= tail-node (.get_tail sll)))))
22+
23+
(deftest test-push-front
24+
(let [sll (sll/->SLL nil nil)]
25+
(.push_front sll "data1")
26+
(.push_front sll "data2")
27+
(is (= "data2" (.get_data (.get_head sll))))
28+
(is (= "data1" (.get_data (.get_addr (.get_head sll)))))))
29+
30+
(deftest test-push-back
31+
(let [sll (sll/->SLL nil nil)]
32+
(.push_back sll "data1")
33+
(.push_back sll "data2")
34+
(is (= "data2" (.get_data (.get_tail sll))))
35+
(is (= "data1" (.get_data (.get_head sll))))))
36+
37+
(deftest test-pop-front
38+
(let [sll (sll/->SLL nil nil)]
39+
(.push_back sll "head")
40+
(.push_back sll "tail")
41+
(.pop_front sll)
42+
(is (= "tail" (.get_data (.get_head sll))))))
43+
44+
(deftest test-pop-back
45+
(let [sll (sll/->SLL nil nil)]
46+
(.push_back sll "head")
47+
(.push_back sll "tail")
48+
(.pop_back sll)
49+
(is (= "head" (.get_data (.get_head sll))))))
50+
51+
(deftest test-insert
52+
(let [sll (sll/->SLL nil nil)]
53+
(.push_back sll "data1")
54+
(.push_back sll "data2")
55+
(.insert sll 1 "middle")
56+
(is (= "middle" (.get_data (.get_addr (.get_head sll)))))))
57+
58+
(deftest test-search
59+
(let [sll (sll/->SLL nil nil)]
60+
(.push_back sll "data1")
61+
(.push_back sll "data2")
62+
(is (= 0 (.search sll "data1")))
63+
(is (= 1 (.search sll "data2")))
64+
(is (= -1 (.search sll "data3")))))

0 commit comments

Comments
 (0)