-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,5 @@ great variety of applications. | |
## implementations | ||
|
||
- [x] Stack (LIFO) | ||
- [x] Linked list | ||
- [ ] ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
module adt | ||
|
||
pub struct ListNode<T> { | ||
mut: | ||
data T | ||
next &ListNode<T> = 0 | ||
} | ||
|
||
pub struct LinkedList<T> { | ||
mut: | ||
head &ListNode<T> = 0 | ||
len int | ||
} | ||
|
||
// is_empty checks if the linked list is empty | ||
pub fn (list LinkedList<T>) is_empty() bool { | ||
return list.len == 0 | ||
} | ||
|
||
// len returns the length of the linked list | ||
pub fn (list LinkedList<T>) len() int { | ||
return list.len | ||
} | ||
|
||
// first returns the first element of the linked list | ||
pub fn (list LinkedList<T>) first() ?T { | ||
return if !list.is_empty() { list.head.data } else { error('Linked list is empty') } | ||
} | ||
|
||
// last returns the last element of the linked list | ||
pub fn (list LinkedList<T>) last() ?T { | ||
if list.head == 0 { | ||
return error('Linked list is empty') | ||
} else { | ||
mut node := list.head | ||
for node.next != 0 { | ||
node = node.next | ||
} | ||
return node.data | ||
} | ||
} | ||
|
||
// push adds an element to the end of the linked list | ||
pub fn (mut list LinkedList<T>) push(item T) { | ||
new_node := &ListNode{ | ||
data: item | ||
} | ||
if list.head == 0 { | ||
// first node case | ||
list.head = new_node | ||
} else { | ||
mut node := list.head | ||
for node.next != 0 { | ||
node = node.next | ||
} | ||
node.next = new_node | ||
} | ||
list.len += 1 | ||
} | ||
|
||
// pop removes the last element of the linked list | ||
pub fn (mut list LinkedList<T>) pop() ?T { | ||
if list.head == 0 { | ||
return error('Linked list is empty') | ||
} | ||
mut node := list.head | ||
mut to_return := node.data | ||
if node.next == 0 { | ||
// first node case | ||
// set to null | ||
list.head = voidptr(0) | ||
} else { | ||
for node.next.next != 0 { | ||
node = node.next | ||
} | ||
to_return = node.next.data | ||
// set to null | ||
node.next = voidptr(0) | ||
} | ||
list.len -= 1 | ||
return to_return | ||
} | ||
|
||
// shift removes the first element of the linked list | ||
pub fn (mut list LinkedList<T>) shift() ?T { | ||
if list.head == 0 { | ||
return error('Linked list is empty') | ||
} else { | ||
list.len -= 1 | ||
node := list.head | ||
list.head = node.next | ||
return node.data | ||
} | ||
} | ||
|
||
// insert adds an element to the linked list at the given index | ||
pub fn (mut list LinkedList<T>) insert(idx int, item T) ? { | ||
if idx < 0 || idx > list.len { | ||
return error('Index out of bounds') | ||
} else if list.len == 0 { | ||
list.push(item) | ||
} else { | ||
list.len += 1 | ||
mut node := list.head | ||
|
||
if idx == 0 { | ||
// first node case | ||
list.head = &ListNode{ | ||
data: item | ||
next: node | ||
} | ||
} else { | ||
for i := 0; i < idx - 1; i++ { | ||
node = node.next | ||
} | ||
node.next = &ListNode{ | ||
data: item | ||
next: node.next | ||
} | ||
} | ||
} | ||
} | ||
|
||
// prepend adds an element to the beginning of the linked list (equivalent to insert(0, item)) | ||
pub fn (mut list LinkedList<T>) prepend(item T) { | ||
list.insert(0, item) or {} | ||
} | ||
|
||
// str returns a string representation of the linked list | ||
pub fn (list LinkedList<T>) str() string { | ||
mut result_array := []T{} | ||
mut node := list.head | ||
for node != 0 { | ||
result_array << node.data | ||
node = node.next | ||
} | ||
return result_array.str() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
module adt | ||
|
||
fn test_is_empty() { | ||
mut list := LinkedList<int>{} | ||
assert list.is_empty() == true | ||
list.push(1) | ||
assert list.is_empty() == false | ||
} | ||
|
||
fn test_len() ? { | ||
mut list := LinkedList<int>{} | ||
assert list.len() == 0 | ||
list.push(1) | ||
assert list.len() == 1 | ||
list.pop() ? | ||
assert list.len() == 0 | ||
} | ||
|
||
fn test_first() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
assert list.first() ? == 1 | ||
list.push(2) | ||
assert list.first() ? == 1 | ||
list = LinkedList<int>{} | ||
list.first() or { return } | ||
assert false | ||
} | ||
|
||
fn test_last() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
assert list.last() ? == 1 | ||
list.push(2) | ||
assert list.last() ? == 2 | ||
list = LinkedList<int>{} | ||
list.last() or { return } | ||
assert false | ||
} | ||
|
||
fn test_push() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
assert list.last() ? == 1 | ||
list.push(2) | ||
assert list.last() ? == 2 | ||
list.push(3) | ||
assert list.last() ? == 3 | ||
} | ||
|
||
fn test_pop() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
list.push(2) | ||
list.push(3) | ||
assert list.pop() ? == 3 | ||
list.push(4) | ||
assert list.pop() ? == 4 | ||
assert list.pop() ? == 2 | ||
list = LinkedList<int>{} | ||
list.pop() or { return } | ||
assert false | ||
} | ||
|
||
fn test_shift() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
list.push(2) | ||
list.push(3) | ||
assert list.shift() ? == 1 | ||
list.push(4) | ||
assert list.shift() ? == 2 | ||
assert list.shift() ? == 3 | ||
list = LinkedList<int>{} | ||
list.shift() or { return } | ||
assert false | ||
} | ||
|
||
fn test_insert() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
list.push(2) | ||
list.push(3) | ||
list.insert(1, 111) or { return } | ||
assert true | ||
} | ||
|
||
fn test_prepend() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
list.push(2) | ||
list.push(3) | ||
list.prepend(111) | ||
assert list.first() ? == 111 | ||
} | ||
|
||
fn test_str() ? { | ||
mut list := LinkedList<int>{} | ||
list.push(1) | ||
list.push(2) | ||
list.push(3) | ||
assert list.str() == '[1, 2, 3]' | ||
} |