mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
adt: add linked list (#12937)
This commit is contained in:
parent
fa2de89db9
commit
54a6973548
@ -6,4 +6,5 @@ great variety of applications.
|
||||
## implementations
|
||||
|
||||
- [x] Stack (LIFO)
|
||||
- [x] Linked list
|
||||
- [ ] ...
|
||||
|
138
vlib/adt/linked_list.v
Normal file
138
vlib/adt/linked_list.v
Normal file
@ -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()
|
||||
}
|
103
vlib/adt/linked_list_test.v
Normal file
103
vlib/adt/linked_list_test.v
Normal file
@ -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]'
|
||||
}
|
Loading…
Reference in New Issue
Block a user