Skip to content

Commit 0fa8652

Browse files
committed
linked list
1 parent 552e42d commit 0fa8652

File tree

6 files changed

+515
-1
lines changed

6 files changed

+515
-1
lines changed

structures/.gitkeep

Whitespace-only changes.
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
package linkedlist
2+
3+
// https://en.wikipedia.org/wiki/Linked_list
4+
5+
// LinkType represents type of linking used in list
6+
type LinkType int
7+
8+
const (
9+
TypeSinglyLinked LinkType = iota + 1
10+
TypeDoubleLinked
11+
TypeCircular
12+
)
13+
14+
// List is linked list
15+
type List struct {
16+
head *Node
17+
lType LinkType
18+
}
19+
20+
// Node of a list
21+
type Node struct {
22+
data interface{}
23+
prev *Node
24+
next *Node
25+
}
26+
27+
// NewList creates new list of given type
28+
func NewList(t LinkType) *List {
29+
return &List{lType: t}
30+
}
31+
32+
// Len of a list
33+
func (l *List) Len() int {
34+
var ret int
35+
36+
switch l.lType {
37+
case TypeSinglyLinked:
38+
for i := l.head; i != nil; i = i.next {
39+
ret++
40+
}
41+
case TypeDoubleLinked:
42+
case TypeCircular:
43+
}
44+
45+
return ret
46+
}
47+
48+
// Values returns all values is the same order they are in list
49+
func (l *List) Values() []interface{} {
50+
ret := make([]interface{}, 0)
51+
52+
switch l.lType {
53+
case TypeSinglyLinked:
54+
for i := l.head; i != nil; {
55+
ret = append(ret, i.data)
56+
i = i.next
57+
}
58+
case TypeDoubleLinked:
59+
case TypeCircular:
60+
}
61+
return ret
62+
}
63+
64+
// Append value to list
65+
func (l *List) Append(v interface{}) {
66+
n := &Node{data: v}
67+
switch l.lType {
68+
case TypeSinglyLinked:
69+
// insert node in empty list
70+
if l.head == nil {
71+
l.head = n
72+
} else {
73+
// find last node in list
74+
last := l.head
75+
for last.next != nil {
76+
last = last.next
77+
}
78+
last.next = n
79+
}
80+
case TypeDoubleLinked:
81+
case TypeCircular:
82+
}
83+
}
84+
85+
// Prepend value to list
86+
func (l *List) Prepend(v interface{}) {
87+
n := &Node{data: v}
88+
switch l.lType {
89+
case TypeSinglyLinked:
90+
n.next = l.head
91+
l.head = n
92+
case TypeDoubleLinked:
93+
case TypeCircular:
94+
}
95+
}
96+
97+
// Traverse list with given callback
98+
func (l *List) Traverse(f func(n *Node) bool) {
99+
switch l.lType {
100+
case TypeSinglyLinked:
101+
for i := l.head; i != nil; i = i.next {
102+
if ok := f(i); !ok {
103+
break
104+
}
105+
}
106+
case TypeDoubleLinked:
107+
case TypeCircular:
108+
}
109+
}
110+
111+
// SearchIdx returns node by given index or nil
112+
func (l *List) SearchIdx(idx int) *Node {
113+
if l.head == nil || idx < 0 {
114+
return nil
115+
}
116+
117+
var n *Node
118+
119+
switch l.lType {
120+
case TypeSinglyLinked:
121+
n = l.head
122+
for i := 0; i < idx; i++ {
123+
if n.next == nil {
124+
return nil // index out of range
125+
}
126+
n = n.next
127+
}
128+
case TypeDoubleLinked:
129+
case TypeCircular:
130+
}
131+
132+
return n
133+
}
134+
135+
// SearchValue returns first found node by given value or nil
136+
func (l *List) SearchValue(v interface{}) *Node {
137+
if l.head == nil {
138+
return nil
139+
}
140+
141+
switch l.lType {
142+
case TypeSinglyLinked:
143+
for n := l.head; n != nil; n = n.next {
144+
if n.data == v {
145+
return n
146+
}
147+
}
148+
case TypeDoubleLinked:
149+
case TypeCircular:
150+
}
151+
152+
return nil
153+
}
154+
155+
// DeleteIdx removes node by its index
156+
func (l *List) DeleteIdx(idx int) bool {
157+
if l.head == nil || idx < 0 {
158+
return false
159+
}
160+
161+
switch l.lType {
162+
case TypeSinglyLinked:
163+
// special case if we are deleting head
164+
if idx == 0 {
165+
l.head = l.head.next
166+
return true
167+
}
168+
// find previous node
169+
prev := l.SearchIdx(idx - 1)
170+
if prev == nil {
171+
return false
172+
}
173+
prev.next = prev.next.next
174+
return true
175+
case TypeDoubleLinked:
176+
case TypeCircular:
177+
}
178+
179+
return false
180+
}
181+
182+
// DeleteValue removes firs occurrence of a node with given value
183+
func (l *List) DeleteValue(v interface{}) bool {
184+
if l.head == nil {
185+
return false
186+
}
187+
188+
switch l.lType {
189+
case TypeSinglyLinked:
190+
var prev *Node
191+
for n := l.head; n != nil; n = n.next {
192+
if n.data == v { // found
193+
if prev == nil {
194+
l.head = l.head.next
195+
} else {
196+
prev.next = n.next
197+
}
198+
return true
199+
}
200+
prev = n
201+
}
202+
case TypeDoubleLinked:
203+
case TypeCircular:
204+
}
205+
206+
return false
207+
}
208+
209+
// UpdateIdx updates value of node with given index
210+
func (l *List) UpdateIdx(idx int, v interface{}) bool {
211+
if n := l.SearchIdx(idx); n != nil {
212+
n.data = v
213+
return true
214+
}
215+
return false
216+
}
217+
218+
// UpdateValue updates value of a first found node with given value
219+
func (l *List) UpdateValue(s, v interface{}) bool {
220+
if n := l.SearchValue(s); n != nil {
221+
n.data = v
222+
return true
223+
}
224+
return false
225+
}
226+
227+
// Merge two linked lists
228+
func (l *List) Merge(with *List) {
229+
if with.head == nil {
230+
return
231+
}
232+
233+
switch l.lType {
234+
case TypeSinglyLinked:
235+
last := l.head
236+
for last.next != nil {
237+
last = last.next
238+
}
239+
last.next = with.head
240+
case TypeDoubleLinked:
241+
case TypeCircular:
242+
}
243+
}
244+
245+
// Sort linked list with provided sorting function
246+
func (l *List) Sort(fn func(v1, v2 interface{}) bool) {
247+
if l.head == nil {
248+
return
249+
}
250+
251+
switch l.lType {
252+
case TypeSinglyLinked:
253+
for {
254+
var (
255+
prev *Node
256+
dryRun = true
257+
)
258+
for i := l.head; i.next != nil; {
259+
// check if we need to swap them
260+
if fn(i.data, i.next.data) {
261+
// create temporary nodes
262+
var (
263+
tmpCurr = &Node{}
264+
tmpNext = &Node{}
265+
)
266+
267+
tmpCurr.data = i.next.data
268+
tmpCurr.next = tmpNext
269+
tmpNext.data = i.data
270+
tmpNext.next = i.next.next
271+
272+
if prev == nil { // means we are at pos 0 (head)
273+
l.head = tmpCurr // new head
274+
} else {
275+
prev.next = tmpCurr
276+
}
277+
278+
prev = tmpCurr
279+
i = tmpNext
280+
281+
dryRun = false
282+
283+
continue
284+
}
285+
286+
prev = i
287+
i = i.next
288+
}
289+
290+
if dryRun {
291+
break
292+
}
293+
}
294+
case TypeDoubleLinked:
295+
case TypeCircular:
296+
}
297+
}

0 commit comments

Comments
 (0)